{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "3068c6e9",
   "metadata": {},
   "source": [
    "### RNA 逆转录 Baseline (Based on RDesign)\n",
    "This code establishes a baseline for ​RNA inverse folding​ (sequence design from structure), adapted from [A4Bio/RDesign](https://github.com/A4Bio/RDesign). It processes RNA structural coordinates (.npy files) paired with sequences (FASTA), splits data into train/valid/test sets, and creates PyTorch datasets where inputs are 3D backbone coordinates (P, C4', O3' atoms) and targets are corresponding RNA sequences. \n",
    "\n",
    "RNA有四种碱基：AGCU, adenine（腺嘌呤）、 Uracil（尿嘧啶）, Cytosine（胞嘧啶）和 Guanine（鸟嘌呤）\n",
    "\n",
    "RNA的序列结构：\n",
    "\n",
    "            碱基                碱基                 碱基\n",
    "磷酸基团-五碳糖(核糖)-磷酸基团-五碳糖(核糖)-磷酸基团-五碳糖(核糖)\n",
    "\n",
    "\n",
    "```text\n",
    "主链方向：C5' → C3'\n",
    "  ...-P-O5'–C5'–C4'–C3'–O3'-P-...\n",
    "            |     \n",
    "            C1'  \n",
    "            / \\ \n",
    "            碱基\n",
    "核糖(5碳糖)主链原子（O5'-C5'-C4'-C3'-O3'），磷酸基团P，碱基N1/N9\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "a1a25400",
   "metadata": {},
   "outputs": [],
   "source": [
    "# !pip install torch, pandas, biopython"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "159f7029-9f98-48b1-aa8f-d3ab43894deb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import torch\n",
    "import random\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import torch.nn as nn\n",
    "from tqdm import tqdm\n",
    "from typing import List\n",
    "from torch.optim import Adam\n",
    "import torch.nn.functional as F\n",
    "from torch.utils.data import Dataset\n",
    "from torch.utils.data import DataLoader\n",
    "from dataclasses import dataclass, field\n",
    "from torch_scatter import scatter_sum, scatter_softmax\n",
    "from Bio import SeqIO  # pip install biopython\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "1faeb703",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "d:\\OneDrive - stu.ahu.edu.cn\\RNA预测\\sais_medicine\n"
     ]
    }
   ],
   "source": [
    "# Define Configuration Classes\n",
    "from typing import Dict\n",
    "\n",
    "\n",
    "root_dir = os.path.dirname(os.getcwd())\n",
    "print(root_dir)\n",
    "datapath = 'saistraindata'\n",
    "datapath = 'saisdata'\n",
    "@dataclass\n",
    "class DataConfig:\n",
    "    fasta_data_path: str = f'{root_dir}/{datapath}/seqs'  # 标签数据\n",
    "    coords_data_path: str = f'{root_dir}/{datapath}/coords'  # 特征数据\n",
    "    outputs_path: str = f'{root_dir}/outputs'\n",
    "    \n",
    "    train_npy_data_dir: str = f'{root_dir}/{datapath}/coords'\n",
    "    valid_npy_data_dir: str = f'{root_dir}/{datapath}/coords'\n",
    "    test_npy_data_dir: str = f'{root_dir}/{datapath}/coords'\n",
    "    \n",
    "    train_data_path: str = f'{root_dir}/outputs/public_train_data.csv'\n",
    "    valid_data_path: str = f'{root_dir}/outputs/public_valid_data.csv'\n",
    "    test_data_path: str = f'{root_dir}/outputs/public_test_data.csv'\n",
    "\n",
    "@dataclass\n",
    "class ModelConfig:\n",
    "    smoothing: float = 0.1\n",
    "    hidden: int = 128\n",
    "    vocab_size: int = 4  # 明确指定为 int 类型\n",
    "    k_neighbors: int = 30  # 明确指定为 int 类型\n",
    "    dropout: float = 0.1\n",
    "    node_feat_types: List[str] = field(default_factory=lambda: ['angle', 'distance', 'direction'])  # 使用 field 避免可变对象问题\n",
    "    edge_feat_types: List[str] = field(default_factory=lambda: ['orientation', 'distance', 'direction'])  # 同上\n",
    "    num_encoder_layers: int = 3\n",
    "    num_decoder_layers: int = 3  # 修正为整数，去掉多余的小数点\n",
    "\n",
    "@dataclass\n",
    "class TrainConfig:\n",
    "    batch_size: int = 8\n",
    "    epoch: int = 100\n",
    "    lr: float = 0.001\n",
    "    output_dir: str = f'{root_dir}/code/weights'\n",
    "    ckpt_path: str = f'{root_dir}/code/weights/best.pt'\n",
    "\n",
    "@dataclass\n",
    "class Config:\n",
    "    pipeline: str = 'train'\n",
    "    seed: int = 2025\n",
    "    device: str = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
    "    data_config: DataConfig = DataConfig()\n",
    "    model_config: ModelConfig = ModelConfig()\n",
    "    train_config: TrainConfig = TrainConfig()\n",
    "    seq_vocab:  List = \"AUCG\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f6c9a137",
   "metadata": {},
   "source": [
    "### Data processing\n",
    "This code implements an RNA data processing pipeline for machine learning tasks using PyTorch and Biopython."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a6c2f4ec-4be4-4b8f-a0c6-d213ca157a86",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████| 2317/2317 [00:00<00:00, 12095.80it/s]\n"
     ]
    }
   ],
   "source": [
    "# Define function to read FASTA files using Biopython\n",
    "def read_fasta_biopython(file_path):\n",
    "    sequences = {}\n",
    "    for record in SeqIO.parse(file_path, \"fasta\"):\n",
    "        sequences[record.id] = str(record.seq)\n",
    "    return sequences\n",
    "\n",
    "# 读取FASTA文件，即标签\n",
    "train_file_list = os.listdir(DataConfig.fasta_data_path)\n",
    "content_dict = {\n",
    "    \"pdb_id\": [],\n",
    "    \"seq\": []\n",
    "}\n",
    "for file in tqdm(train_file_list):\n",
    "    data_path = os.path.join(DataConfig.fasta_data_path, file)\n",
    "    sequences = read_fasta_biopython(data_path)\n",
    "    content_dict[\"pdb_id\"].append(list(sequences.keys())[0])\n",
    "    content_dict[\"seq\"].append(list(sequences.values())[0])\n",
    "\n",
    "data = pd.DataFrame(content_dict)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "1ffa5dce",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'d:\\\\OneDrive - stu.ahu.edu.cn\\\\RNA预测\\\\sais_medicine/outputs/public_train_data.csv'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# data.to_csv('../outputs/labels.csv', index=False, columns=[\"pdb_id\", \"seq\"])\n",
    "DataConfig.train_data_path"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b4968da",
   "metadata": {},
   "source": [
    "## 拆分训练集, 测试集和验证集"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "3a924975-46ec-49ab-a115-8487f96aa142",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Split data into train, validation, and test sets\n",
    "import os\n",
    "\n",
    "\n",
    "os.makedirs(DataConfig.outputs_path, exist_ok=True)\n",
    "np.random.seed(42)\n",
    "split = np.random.choice(['train', 'valid', 'test'], size=len(data), p=[0.7, 0.2, 0.1])\n",
    "data['split'] = split\n",
    "train_data = data[data['split']=='train']\n",
    "valid_data = data[data['split']=='valid']\n",
    "test_data = data[data['split']=='test']\n",
    "train_data.to_csv(DataConfig.train_data_path, index=False)\n",
    "valid_data.to_csv(DataConfig.valid_data_path, index=False)\n",
    "test_data.to_csv(DataConfig.test_data_path, index=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa48eb54",
   "metadata": {},
   "source": [
    "## 读一下数据"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4678b144",
   "metadata": {},
   "outputs": [],
   "source": [
    "data_path = f\"{DataConfig.coords_data_path}/1A9N_1_Q.npy\"\n",
    "data_path = f\"{DataConfig.coords_data_path}/3JBU_1_v.npy\"\n",
    "\n",
    "coords = np.load(data_path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f9ee6dd7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(76, 7, 3)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coords.shape  # (n, 7, 3), n是n个原子基团, 7是每个基团的7种原子, 3是三维坐标"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "8be4df7f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[198.192, 224.987, 187.735],\n",
       "       [198.123, 223.434, 188.093],\n",
       "       [199.002, 222.475, 187.463],\n",
       "       [198.757, 221.067, 187.972],\n",
       "       [197.477, 220.817, 188.763],\n",
       "       [196.374, 220.59 , 187.888],\n",
       "       [199.554, 220.553, 191.197]], dtype=float32)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "coords[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9760eda1",
   "metadata": {},
   "source": [
    "## 可视化\n",
    "\n",
    "+ 缺失值最好用相同碱基的均值填充\n",
    "+ 临近碱基通过均值计算邻域"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "b2036844",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(140, 3) (140,)\n",
      "<matplotlib.colors.ListedColormap object at 0x0000023638700460>\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAIvCAYAAACSkRrWAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOy9e3gc9X3v/5qZva8uq9VdsmzJtny3AWMMkgGHEiBJQ8k5J21OSNsH6C0HQpKaJL/mVhLSkoST0hQMpE2TkrSQ9JwQztMrmDglONiAE5Cvsm6WbMvS6raSVqu9z8zvDzHjXd1XmpVG9ryexw9od2fmO7Oz3+97PldBVVUVCwsLCwsLC4vLFHG5B2BhYWFhYWFhkUsssWNhYWFhYWFxWWOJHQsLCwsLC4vLGkvsWFhYWFhYWFzWWGLHwsLCwsLC4rLGEjsWFhYWFhYWlzWW2LGwsLCwsLC4rLHEjoWFhYWFhcVljSV2LCwsLCwsLC5rLLFjYWFhYWFhcVljiR0LCwsLCwuLyxpL7FhYWFhYWFhc1lhix8LCwsLCwuKyxhI7FhYWFhYWFpc1ltixsLCwsLCwuKyxLfcALCwsLCwslgtZlkkmk8s9jCsCu92OJEnLcmxL7FhYWFhYXHGoqkogEGBkZGS5h3JF4fP5qKioQBCEJT2uJXYsLCwsLK44NKFTVlaGx+NZ8sX3SkNVVSKRCP39/QBUVlYu6fEtsWNhYWFhcUUhy7IudIqLi5d7OFcMbrcbgP7+fsrKypbUpWUFKFtYWFhYXFFoMToej2eZR3LloV3zpY6TssSOhYWFhcUVieW6WnqW65pbYsfCwsLCwsLissYSOxYWFhYWFhaXNZbYsbCwsLCwWCEEAgEefPBB1q5di9PppKamhjvvvJODBw/Out0LL7zAli1bcDqdbNmyhRdffHHOY504cYK9e/fidruprq7mkUceQVVVo05lSbHEjoWFhYWFxQqgq6uLa6+9lp///Oc89thjnDhxgpdeeolbbrmFBx54YMbtjhw5wkc+8hF+7/d+j2PHjvF7v/d7/M7v/A5vvvnmjNuEQiFuu+02qqqqOHr0KE8++STf+ta3ePzxx3NxajlHUFeqTLOwsLCwsFgAsViMzs5O6urqcLlci9rX2YEw54IRaou91JV4DRrh9HzgAx/g+PHjtLS04PVmHmtkZASfzzftdh/5yEcIhUL853/+p/7a+973PoqKivjRj3407TbPPPMMn//85+nr68PpdALwjW98gyeffJLu7u4FBxobee2zwbLsWFhYWFhYZMlIJMHvf+8tfuOvfsG9/3CUW771Kr//vbcYjeQmpToYDPLSSy/xwAMPTBE6wIxCByYsO7fffnvGa3fccQeHDx+edZu9e/fqQkfbpqenh66urqzHv9xYYsfCwsLCwiJLPvmjJl5vH8x47fX2QR780Ts5OV57ezuqqrJp06astw0EApSXl2e8Vl5eTiAQyHob7b2VhiV2LCwsLCwssuDsQJjX2gaQJ0WByKrKa20DdA6OG35MLeJkoe6jydupqjrnvqbbZjFjWE4ssWNhYWFhYZEF54KRWd/vGjJe7NTX1yMIAs3NzVlvW1FRMcUa09/fP8VyM59tgFm3MyuW2LGwsLCwsMiCNf7Z20zUFhsfqOz3+7njjjt46qmnGB+fKqZm697e0NDAK6+8kvHagQMHaGxsnHWb1157jUQikbFNVVUVtbW1WY9/ubHEjoWFhYWFRRasLc3j5vpSpEnuHEkQuLm+NGdZWU8//TSyLLN7925eeOEF2traaG5u5oknnqChoWHG7T71qU9x4MABvvnNb3LmzBm++c1v8rOf/YxPf/rT+mf279/Prbfeqv99991343Q6ueeeezh58iQvvvgijz76KPv27bPcWBYWFhYWFlcCT370GvasL8l4bc/6Ep786DU5O2ZdXR1vv/02t9xyCw899BDbtm3jtttu4+DBgzzzzDMzbtfY2MiPf/xj/uEf/oEdO3bw7LPP8s///M9cf/31+mcGBwfp6OjQ/y4sLOSVV16hu7ubXbt2cf/997Nv3z727duXs/PLJVadHQsLCwuLKwoja710Do7TNTS+JHV2LgeWq86ObcmOZGFhYWFhcZlRV2KJnJWA5caysLCwsLCwuKyxxI6FhYWFhYXFZY0ldiwsLCwsLCwuayyxY2FhYWFhYXFZY4kdCwsLCwsLi8saS+xYWFhYWFhYXNZYYsfCwsLCwsLissYSOxYWFhYWFhaXNZbYsbCwsLCwWCEEAgEefPBB1q5di9PppKamhjvvvJODBw/OuM2pU6f4H//jf1BbW4sgCHz729+e17FOnDjB3r17cbvdVFdX88gjj7BSmy5YFZQtLCwsLCxWAF1dXezZswefz8djjz3Gjh07SCaTvPzyyzzwwAOcOXNm2u0ikQhr167lt3/7t/nTP/3TeR0rFApx2223ccstt3D06FFaW1u555578Hq9PPTQQ0ae1pJgiR0LCwsLC4sVwP33348gCLz11lt4vZdaVGzdupX77rtvxu2uu+46rrvuOgD+7M/+bF7Heu6554jFYjz77LM4nU62bdtGa2srjz/++IrsfG65sSwsLCwsLBbIWDRFYDhOOJrK6XGCwSAvvfQSDzzwQIbQ0fD5fIYe78iRI+zduxen06m/dscdd9DT00NXV5ehx1oKLMuOhYWFhYVFliRSCkfbRukfTeivlRU6uK6+EIfNeDtCe3s7qqqyadMmw/c9HYFAgNra2ozXysvL9ffq6uqWZBxGYVl2LCwsLCwssuRo2ygDaUIHYGA0wdG20ZwcTwsMXkr30eRjLccYjMISOxYWFhYWFlkwFk3RP5pgcl6SCvSPJnLi0qqvr0cQBJqbmw3f93RUVFQQCAQyXuvv7wcuWXhWEpbYsbBYRlRVJZlMMjY2RiQSIZFIIMvyik3vtLC4EhiPybO+H57j/YXg9/u54447eOqppxgfH5/y/sjIiKHHa2ho4LXXXiORuGS9OnDgAFVVVVPcWysBS+xYWCwTiqKQSCRIJpMkk0lisRjj4+OMjY0RDoeJRqMkk0kURbHEj4WFifC6pFnfz5vj/YXy9NNPI8syu3fv5oUXXqCtrY3m5maeeOIJGhoaZtwukUjQ1NREU1MTiUSCixcv0tTURHt7u/6Z/fv3c+utt+p/33333TidTu655x5OnjzJiy++yKOPProiM7HAClC2sFhyVFVFURRdyAiCgCRJiKKIqqqoqkoqlSKZTCIIgv6+zWbDZrMhSZL+uoWFxdKT77ZRVuhgYJIrSwBKCx3kuXOztNbV1fH222/zl3/5lzz00EP09vZSWlrKtddeyzPPPDPjdj09PVxzzTX639/61rf41re+xd69e3n11VcBGBwcpKOjQ/9MYWEhr7zyCg888AC7du2iqKiIffv2sW/fvpycW64RVOuR0cJiydDcVrI8YeYWBAFVVUkkEojiVEOrJn406066+LHb7UiSpAslCwuL+RGLxejs7KSurg6Xy7WgfSx1NtblghHXfiFYlh0LiyVCs+bIsowoirplZrbnDU3caGJmsuUHQBTFDKuPJX4sLHKPwyayZ3MR4WiKcEwmzyXlzKJjsXisb8bCIseoqoosy6RSKRRFyRA62TKT+Ekmk3ogoeYOczqduvXHEj8WFrkhz22zRM4KwPqGLCxyyGS31WKEznRMJ34UReHo0aOsX7+eoqIiBEGwLD8WFhZXNJbYsbDIEbIs60HIc4kcowSQFs+j/VeSJN19lkgkdHGULn5sNpsV7GxhYXFZY4kdCwuD0WJqUqkUqqrO25qjBSAbOQ5N9KS/Nln8iKI4JeDZEj8WFhaXE5bYsbAwEEVRSKVSWbutjBY6M+1rvuJnstvLEj8WFhYrGUvsWFgYQLpoSE8RX+4xzUW6+NE+rxU7jMfjlvixsLC4LLDEjoXFIkl3WwGmEDoLOb62jSV+LCwsLjcssWNhsQhmqp1jBhZbL3Q28ROPxzNS3S3xY2FhYWYssWNhsQCMrJ2TC3IxlnTxI0mSXuNHVdUp4kcLdrbZbKa7NhYWFlceVrENC4ss0WrnaPE5i13McyUEct0JZrpMLq2godbUNBQKEQqFrI7uFhYGEQgEePDBB1m7di1Op5OamhruvPNODh48OOM23/3ud7npppsoKiqiqKiI9773vbz11ltzHuvEiRPs3bsXt9tNdXU1jzzyyIr9/VqWHQuLLNDiV4y25hgteJbDkpIeqzTZ8vPaa6+xefNmCgoKdMuP5vayLD8WFvOjq6uLPXv24PP5eOyxx9ixYwfJZJKXX36ZBx54gDNnzky73auvvspHP/pRGhsbcblcPPbYY9x+++2cOnWK6urqabcJhULcdttt3HLLLRw9epTW1lbuuecevF4vDz30UC5PMydYYsfCYh5obquWlhaqqqpwu92mX6CX+wksXfyoqjrF8qN9ZnJHd0v8WFhMz/33348gCLz11lt4vV799a1bt3LffffNuN1zzz2X8fd3v/tdfvKTn3Dw4EF+//d/f8ZtYrEYzz77LE6nk23bttHa2srjjz/Ovn37Vtxv1HJjWVjMQbrb6ty5cySTSdP/0M04vsluLy2eRwt4DofDjI2NMTY2Zrm9LFYOg+3Q9goMdeT0MMFgkJdeeokHHnggQ+ho+Hy+ee8rEomQTCbx+/0zfubIkSPs3bsXp9Opv3bHHXfQ09NDV1dXNkM3BZZlx8JiFrSWD2apnZMNZhcJk6+n5vKSZRlZlmdMdbcsPxamIBKEF/4QOtJiZdbdCh/+HriLDD9ce3s7qqqyadOmRe/rz/7sz6iurua9733vjJ8JBALU1tZmvFZeXq6/V1dXt+hxLCWW2LGwmIaZaucIgmB6EQHmtOzMxUwd3SeLH83tld7XayWer8UK54U/hLOvZr529lX4yR/A7/3U8MNp885i7/XHHnuMH/3oR7z66qu4XK5ZPzv5WEaNYTmw3FgWFpPQgpA1oZNuSVgpYgfMb9mZi+msOoIgkEqliEajerZXOBwmGo3qTVdX+nlbrAAG2ycsOqqc+boqT7yeA5dWfX09giDQ3Ny84H1861vf4tFHH+XAgQPs2LFj1s9WVFQQCAQyXuvv7wcuWXhWEpbYsbB4F82KoMWKpFsZNLQYE7OzEp+85iJd/Gip7uniJxwO6+InFovp4sfCwnCGO2d/P3jW8EP6/X7uuOMOnnrqKcbHx6e8PzIyMuv2//t//2++9rWv8dJLL7Fr1645j9fQ0MBrr72m188COHDgAFVVVVPcWysBS+xYWHApCDmRSMxaO8ey7JiH2cRPJBKxxI9F7iiaI17FvzYnh3366aeRZZndu3fzwgsv0NbWRnNzM0888QQNDQ0zbvfYY4/xpS99ie9///vU1tYSCAQIBAKEw2H9M/v37+fWW2/V/7777rtxOp3cc889nDx5khdffJFHH310RWZigSV2LCwy3FbaAjpb1/CVICJW4mS0WGYSP8lkkkgkwtjYmCV+LIyhZP1EMLIgZb4uSBOvF6/LyWHr6up4++23ueWWW3jooYfYtm0bt912GwcPHuSZZ56Zcbunn36aRCLBhz/8YSorK/V/3/rWt/TPDA4O0tFxyf1WWFjIK6+8Qnd3N7t27eL+++9n37597Nu3LyfnlmsEdSXM3BYWOWAhLR9ef/116uvrKSsrM3QcmqnYKJFy7NgxSkpKZiwYttT88pe/ZPv27RQWFi7bGLTO9Kqq0tvbiyzL1NTUTOnrNdl1aXH5EYvF6OzspK6ubs4g3RmJDk8EIy9RNtblgiHXfgFY2VgWVySa20qWJwIM55vOvFIsOxZT0TK5ABKJBMlkEkCvoaR9Jl38aNleFhZTcBdNZF0NdUzE6PjX5syiY7F4LLFjccWh1c5ZSMuHXIkdo/dribK5SRc/cMnyo8VupRdBnJwRZmGhU7zOEjkrAEvsWFwxTK6ds5DidJaIuDyY7jvMRvxoMUGW+LGwWBlYYsfiikBbtLSA1IUWoltJYmeljNOspIsf7VpOJ34mx/xY4sfCwnxYYsfisib96dyITuVWnZ3Lh2zdl8C04ieRSMzY2sISPxYW5sASOxaXLaqqEg6HURQFh8NhSE8ly7JzebDYazOb+InH43p2nSV+LCzMgSV2LC5LNGtOS0sLTqeTDRs2GLLflSJ2zLagmm08YOyY0sWPJEl6Xy9VVS3xY2FhAiyxY3FZMV3tnCs1y2mljHM50LrY54r0mLDpxE+628tut1sd3S0scowldiwuG6arnXOlih1rwTQXs4mfWCwGTPQ2cjqdFBUVWeLHwsJgLLFjcVkwU+0cQRAMDSheKWIHLMvOXCyniJhO/AQCAfLz83G73fpnJtf4scSPhcXCsOqiW6xo0ht4TpdttZIsO0aP02JmzCYE04WP5tbSMv9isRjhcJixsTHGxsaIRCIkEglkWTbdeVjknkAgwIMPPsjatWtxOp3U1NRw5513cvDgwRm3+elPf8quXbvw+Xx4vV6uvvpq/vEf/3HOY504cYK9e/fidruprq7mkUceWbH3nGXZsVixKIpCKpWateXDlVyZeKWMc7kwmyBMjyOaye0lyzKyLM+Y6m5Zfi5vurq62LNnDz6fj8cee4wdO3aQTCZ5+eWXeeCBBzhz5sy02/n9fr74xS+yadMmHA4H//Zv/8a9995LWVkZd9xxx7TbhEIhbrvtNm655RaOHj1Ka2sr99xzD16vl4ceeiiXp5kTLLFjseJIr52jLRAzTfBG18Wx6uxcHphRCM42Ju0e15qUziZ+tOrOWl8v6164fLj//vsRBIG33noLr9erv75161buu+++Gbd7z3vek/H3pz71KX7wgx/wy1/+ckax89xzzxGLxXj22WdxOp1s27aN1tZWHn/8cfbt27fi7ivLjWWxotBaPiQSiTmFDliWHYuVQzYZYtNZdQRBQJZlotEo4+PjhEIhwuEw0WhUj2ez7okcMD4Agy0QGczpYYLBIC+99BIPPPBAhtDR8Pl889qPqqocPHiQlpYWbr755hk/d+TIEfbu3YvT6dRfu+OOO+jp6aGrqyvb4S87lmXHYsWgWXNkWc54yp2NKzVAeaU9dS01uU49XwiLGdNMlp9UKkUymdTfn9zXaz6/IYsZSEbgxI8h2HbpNX89bP8o2N2GH669vR1VVdm0adOCth8dHaW6upp4PI4kSTz99NPcdtttM34+EAhQW1ub8Vp5ebn+Xl1d3YLGsVxYYsfC9ExXO2e+i8JKClA2kpUyTotLGCnALPGzBJz4MQTbM18LtsOJH8HOmV1KC0X7PS/0HsnPz6epqYlwOMzBgwfZt28fa9euneLiSmfysRY7huXEEjsWpma62jnZ9jS6EsWOxcojl9amucQPTF/d2RI/MzA+kGnR0VEnXo8MgqfE0EPW19cjCALNzc186EMfynp7URRZv349AFdffTXNzc18/etfn1HsVFRUEAgEMl7r7+8HLll4VhLWnWxhWrQ+Q6lUSp+os10MjA4oXiliZ6WMc7kwoxsLlu6JOT3mR0t1FwSBZDJJJBIhHA7rMT+xWEyP+bF4l2hw9vcjQ4Yf0u/3c8cdd/DUU08xPj4+5f2RkZGs9qdV856JhoYGXnvtNb3VCcCBAweoqqqa4t5aCVhix8J0aE+c8Xh80Z3KV4Jlx8qYsYDlFWCTxY/W4LS3t5c333xzWvFzRYtpt3/29z3FOTns008/jSzL7N69mxdeeIG2tjaam5t54oknaGhomHG7r3/967zyyiucPXuWM2fO8Pjjj/PDH/6Q3/3d39U/s3//fm699Vb977vvvhun08k999zDyZMnefHFF3n00UdXZCYWWG4sC5OxWLfVZK7kAGWzjdNM4zGjZcdMY9LieTQkSdITBBKJhC7QNbdXekbYFYG3dCIYOdgOpN/XAvjXG+7C0qirq+Ptt9/mL//yL3nooYfo7e2ltLSUa6+9lmeeeWbG7cbHx7n//vvp7u7G7XazadMm/umf/omPfOQj+mcGBwfp6OjQ/y4sLOSVV17hgQceYNeuXRQVFbFv3z727duXk3PLNYJqphnI4opGlmXOnz+P0+nE7/cbMnEGAgE6OztnferJho6ODsbHx9mxY4ch+9OIRCIA2GzGPH+0tU3EE9TX1xuyv8Xy+uuvs3Xr1nmnx+aaU6dO4fV6TWWOf+utt6irq6O0tHS5h6LT09NDX18f11xzTcbrWq0rLfZHswxNDng2q/iJxWJ0dnZSV1eHy+Va2E6S0Ylg5CXKxrpcMOTaLwDLsmOx7Ghuq1QqRX9/P/n5+RQXG2MGXglurIsXL3Lq1Clg4mnK7/dTVFREfn7+otx3VozFysJMlh2NmcY02fKTXuhTs/xMF/BstvNbFHb3RNZVZHAiRsdTnDOLjsXiscSOxbKiTZDawmx0qriZA5RlWeb06dP09/dz1VVXYbPZGBkZYXh4mHPnzgFQVFSk//N4PJfXYrGMrCRhsZyoqjrvelaa+NF+H4qikEgkZmxtcdmIH0+JJXJWAJbYsVgW0p8E04OQzV4Xx6j9hcNhmpqasNvt7NmzB5vNRiqVIj8/n5qaGlRVZWxsjGAwyMDAAO3t7dhsNoqKinTLz1wmYMtDPTtmXGjNNiZFUbIeU3pPL7gCxY+FKbHEjsWSM1sQci4sMWaz7PT09HDq1ClWr15NfX09oijqtU7Sj1NQUEBBQQG1tbXIskwoFCIYDHLx4kXOnDmDy+XShU9RURF2uz1je4uVxUKERa4xwto0nfjR/sXjcT212RI/FrnEEjsWS0p6y4eZupQb3bjTLJYdWZZpbm6mr6+Pq6++OqtAVEmSdFEDkEqlGBkZIRgM0tnZycmTJ8nLy9PFj9UHaXbMem3MtrhrVlcjmamjuyZ+ZmpqanV0t1gMltixWBLm2/JBFEXd4mMEZnFjaW4rm81GY2MjbvfisjVsNhslJSWUlEzECiQSCYaHhwkGg7S0tBCLxXA4HJw9exa/309BQcGyVsM14yJltjGZNWYn12OaTfzEYjH9M5r40Sw/lvixyAZL7FjknGxq50zn0lkMZghQns5tZTQOh4Py8nK9jHtLSwvhcJhIJMLFixdRFCUj0ysvL++KXijMaNm5UsXOZOYjfsLhMKIo4vf7LfFjMS8ssWORU2RZnhKEPBtmECezkc34ZFnmzJkzBAIBrrrqKsrKygwbx1w4HA48Hg+bN29GVVXGx8cZHh5meHiYzs5ORFHE5/Pp4sftdlsLxTJjVgG23P2xphM/AwMDqKqKx+MBJn6Xk2N+LPFjkY4ldixyQnrtHJh/JeRcuJ2WQzyNj4/T1NSEKIqGuK0WQnqH4ry8PPLy8qipqUFRFMbGxhgeHqavr4/W1lYcDoceE+T3+3E6nUs+3qXGbAuhGS07Zgya1n6DWgFDzeqj9dKLxWKW+LGYgiV2LAxncu2cbHo/GW3ZWY4A5d7eXk6ePElNTQ0bNmyYd50SI5ltf6IoUlhYSGFhoZ7pNTo6yvDwMN3d3TQ3N+PxeHTh4/P5MjK9LgfMakUx22JsBsvOdCiKot+Tk+cXTfzIsowsy9MGPFsFN688zHcXW6xYtAkmkUjoT4TZPk3lyo1l1OI2m9iRZZlTp05x+vRprrrqKjZt2rSsC8V8z1mSJPx+P+vWreO6667jpptuYt26dQiCwNmzZzl06BBHjx6lvb2dYDBoaAD5cmI2YQHmG1MusrGMYLZxTVfDRxAEZFkmGo0yPj5OOBxGURT9n5FzRK4JBAI8+OCDrF27FqfTSU1NDXfeeScHDx6c1/Y//vGPEQSBD33oQ3N+9sSJE+zduxe32011dTWPPPLIirlOk7EsOxaGMDkIeaGdvHMRY6ONz4iFZKbxRSIRmpqaEASBhoYGPZZguVjMudrtdkpLS/XU+Hg8rsf7NDc3k0gkKCws1C0/+fn5plwQZ8OME7ZZLTtmGxNkZ3HS5qL0uUBzr2tiJ/1zk//fTHR1dbFnzx58Ph+PPfYYO3bsIJlM8vLLL/PAAw9w5syZWbc/d+4cn/nMZ7jpppvmPFYoFOK2227jlltu4ejRo7S2tnLPPffg9Xp56KGHjDqlJcMSOxaLZq7aOdmQC8sOGLe4TSd2AoEAJ0+epLq6mo0bNy5o4c+FG8uoc3Y6nVRUVFBRUYGqqkSjUV38dHd3oygKPp9PFz9er9eUC4XZMaOwMOOYYHEWp3Tho4ma9Iyv9M+ZTfzcf//9CILAW2+9hdfr1V/funUr991336zbyrLMxz72Mb761a9y6NAhRkZGZv38c889RywW49lnn8XpdLJt2zZaW1t5/PHH2bdvnymuRzZYYsdiwcy3dk425CJmByYmx/TGhQslXUQoisKZM2fo6elh+/btetr35YwgCHg8HjweD9XV1aiqSjgcnpLpld7TSwvONpM1xYyLuBnHtBLdWAth8nXPRvx0jXZxYewCqwtWs6ZgjWFjmkwwGOSll17iL//yLzOEjobP55t1+0ceeYTS0lL+4A/+gEOHDs15vCNHjrB3796MZIU77riDz3/+83R1dVFXV5f1OSwnltixWBBaOnNLSwubN282LNMhF9lYYLxlR3NbATQ2Ni6722oyRl/H2Y6Tn59Pfn4+q1evRlEUQqFQRqaX0+kkmUwSDAbxeDxXRKZXtqRnzpkJMwowyH2W2HzETygR4vOvf57DPYf11/ZU7eGbN3+TQmeh4WNqb29HVVU2bdqU9bavv/463/ve9/Q5az4EAgFqa2szXtMe6AKBgCV2LC5/tNo5iUSC7u5utmzZYtjEkys3llH71IoeHj58mKqqKkODkM1k+VgoWv0en89HXV0dsiwzMjLCyZMn6e/v59y5c3i93gzLj822PNOQmRZxs373ZhY7S2lxmk78/Nkv/4y3Am9lvP5G7xt87rXP8Z33fsfw67ZQQTw2Nsbv/u7v8t3vflevuD5fpjvvhYzBDFhix2LepNfOUVVVX6SMnHjMHLOjKArnzp0jmUxy9dVXU1FRseh9ahi92C2VZWcuJEmiuLgYu93Opk2byMvL011eHR0dRKNR8vPzdeFTWFhoiLtxLsxwbdIx6yJypbixsuX82HmO9B6Z8rqsyhzuOczZ4bPUFtZOcX0thvr6egRBoLm5eV6ZVBodHR10dXVx55136q9pc6zNZqOlpYV169ZN2a6iooJAIJDxWn9/P8CKdNlbYsdiXiiKQiqVymj5oC1KZq54nB6AuBgikQjHjh0jlUpht9sNFTpXEna7nbKyMr2adCwWy8j0SiaTeqZXUVHRisz0WghmFTtmtewsd/2fC2MX5nx/TcGaaWN+Fip+/H4/d9xxB0899RSf/OQnp8TtjIyMTBu3s2nTJk6cOJHx2pe+9CXGxsb4m7/5G2pqaqY9XkNDA1/4whdIJBI4HA4ADhw4QFVV1RT31krg8p9FLBZFeu0cWZYzauekB/8ahdGWHVh8FeW+vj4OHz5MYWEh27dvN3BkucMslp25cLlcVFZWsmXLFhobG7nuuusoLS1lbGyMY8eOcejQIY4fP86FCxcIh8OGnZNZF3Gzjcms12m5LTs1+dMLBI3VBauniButyrNW7FCW5axr/Dz99NPIsszu3bt54YUXaGtro7m5mSeeeIKGhoZpt3G5XGzbti3jn8/nIz8/n23btulCZv/+/dx66636dnfffTdOp5N77rmHkydP8uKLL/Loo4+uyEwssCw7FrMwueXD5PRLo+NhIDdiZ6FVlBVFobW1le7ubrZu3UplZSVjY2MrQkSsRARBwOv14vV6WbVqlZ7pFQwGGRoaoqOjA5vNNm2m10rHrJad5RYVM7Hc41pTsIbGykbeDLyJrF4qsikKIteVXjclKyubbK/ZLD91dXW8/fbb/OVf/iUPPfQQvb29lJaWcu211/LMM88s6pwGBwfp6OjQ/y4sLOSVV17hgQceYNeuXRQVFbFv3z727du3qOMsF5bYsZiW9No56VacdLTXzdzeARZm2YlGozQ1NaEoCg0NDbrJeKVYTFbKOGcjPdNrzZo1KIqit7Xo7e2lpaUFp9OpNzMtKirSn1Lnu3+zYFaxY2bLznKP6xs3foM/++Wfcbj3UjbW7rLdfOW6r8y57WLET2VlJfv372f//v0LHvuzzz475bWvfOUrfOUrmWPfvn07r7322oKPYyYssWORQba1c3IRULzclp3+/n5OnDhBRUUFmzZtygiYXUkiYqWMc76k1+8BSKVSjIyMMDw8zLlz5zh16hR5eXn6Z3w+34yZXma7NmYWO5ZlZ3oKnAU8fevTnAud48LYBWrya6h0VS6onUr6967dCwux/FjMjCV2LHQmt3yYT+2cXFh2chGzM5/FTXNbXbhwga1bt1JVVbXgfS1kjBbZYbPZKCkp0dNpE4kEIyMjBINB2traiMViFBQUZGR6pS+QZrrmZhNfGmawoEyHmUTYmoI1utsqkUgsen8zpXtb4mdxWGLHApiY1LQGntkUCMyVG8tI8/l8rEXRaJRjx44hyzINDQ3k5eUt2fhywUqyQBmFw+HIyPRKb2vR09NDKpWisLAQv9+vl08wC2a27JhxTGaw7ExHLq6XJX6MwRI7Vzia2yqZTOpPS9n8SHJZF8fIQoWzLWwDAwMcP36c8vJyNm/ePGudl1yMzyI3uN1u3G43VVVVetXrYDDI8PAwkUiEM2fO0N/fr1t+PB7Psn2nZr2fzGRB0dB+y2Yb11JhiZ+FYYmdK5iFuK0mk8teVkZNZjNZORRFoa2tjfPnz8/otppuX5CbIoBG789MlovlnmjTM71qamp46623KC8vR1VVBgYGaG9v1zO9tIBnl8u1ZOMzq9gxoxsrvUu52ViO73E+4idd8Fyp4scSO1co6dacySnl2ZBLsWPkPifvLxaLcezYMZLJ5Kxuq8nkSuxYLD0ej4fS0lJqa2uRZZlQKEQwGOTixYucOXMGl8uVkellt9tzOh4zLj5mFGHab/lKtezMxUyZXslkEkVRcDqdV6T4scTOFcZctXOyxcztHdL3mb4/zW1VVlbGli1bsmpPkEuxY+Rkc7lPXEaQfo0kSZo20ysYDNLZ2cnJkyfJy8vTxY/P5zO0rYUZRQWY041lZrFjxu9xujkr3fqT/pnLWfxYYucKQqudY+RkYfbGndo+FUVBURTa29s5d+4cW7Zsobq6esHjM7tlx2xuLLMx17WZLtNreHiYYDBIS0sL8Xhcz/Ty+/0UFBQs6vdkxkUSzOvGWuxDWi4x67hmsuKnu7vSxc9k0WPW85ovlti5AtCyF86dO0dJSQkOh8PQ4F+jhUkuXGOJRIKjR49m7baabnxgfrFjYSwOh4Py8nK9AaKW6aW5vRRF0TO9ioqKyMvLy+o3ZlaxY8ZxmdHapLES54X5FjiEiR6BXq/XtNd/Niyxc5mTHoR86tQpGhsbcTqdhu1/OevizJdkMklbWxvl5eVce+21Mxaam+/YwPyTmmXZmZvFLOKTM73Gx8d18dPZ2Ykoivh8Pl38uN3uWY9nxu/KrFlPZk071zCbONSYr0icSfzIskxLSwtXX321qa//TKy8EVvMG612TiqV0i0mRk+qudqnEQJKVVXa2toYGxujvLycHTt2LErowCXzrtECz2JpMTomLC8vj5qaGq666ipuuukmduzYQX5+Pn19fbz55pscPnyY06dP09vbSzwen3Y8ZlskzZr1ZEbXmsZSiNZAIMCnPvUp6uvr8Xg81NbWctddd3Hw4MEZt/nBD35Afn4+Ho8Hm82m/4vFYrMe68SJE/zGb/wG+fn51NXV8d3vfte0134uLMvOZchMLR8kSVpQKfPZyFXjzsXuMxaLcfz4ceLxOH6/n8LCQoNGtzKsJithjMtNriZtURQpLCyksLBQz/TSenp1d3fT3NyMx+PR4318Pp8pxY5ZCx1eyZadrq4ubr75Znw+H9/4xjfYvn07yWSSAwcO8MlPfpJTp07NuG1BQQHHjh3LyCqcrbxCKBTife97H+95z3t44403OHXqFH/8x39MfX09n/nMZww9r6XAEjuXGbPVzjGrMJnMYhfqoaEhjh07RklJCTt37uTEiROGxxVZQiJ7zHTNlnIskiTh9/vx+/2sW7eOZDKp9/Q6e/Ys4+PjuN1uUqkUwWCQwsJCQzO9ForlxsqeXN9Xn/jEJxAEgSNHjujNiQG2bt3KvffeO+u2giBQUVEx7xIKzz//PLFYjO9///s4nU7Wrl3Lfffdx1//9V/z0EMPmU4Ez4Uldi4jtNo5M7V8WCliZ6H7VFWVjo4OOjs72bx5M9XV1Tlx360EsbMSxnilYrfbKS0tpbS0FIB4PM6FCxe4ePEizc3NJBIJCgsLdctPfn7+sizuZnVjmS1AeTQ5TCg1QoHNh4Q9Z9crGAzy8ssv87WvfS1D6Gj4fL5Ztw+Hw2zYsAFFUbjqqqv46le/yjXXXDPj59944w1uvvlmPcZTlmX27NnDk08+SVdXF3V1dYs6n6XGEjuXAZNr58xUCVmSpJxYYcwgduLxOMePHycajXLDDTeQn5+fMcYrTexYzI6Z3EZOp5OioiKGhobYvXt3Rk+v7u5uFEXB5/Pp4sfr9S7J2C031uzE5CivDv0H3fFz+msVtlX8hvM38UhTxchiaW9vR1VVNm3alPW2Gzdu5Omnn+aaa65hfHycJ598kptvvpm3336b+vr6abcJBALU1tbqfyuKogv0QCBgiR2LpWVy7ZzZ6k+IopiTmB1NZBm5z2zExNDQEMePH8fv93PNNddMCULORXq82cXOShijxSXSa6B4PB48Hg/V1dWoqko4HNbFj5bppRVAnE+m10Ixaz0bswQovzr0H1yMn894rS91kV8Mv8T7y/6H4cdbjPi84YYb2LZtG263G0mS2LNnD9dddx1PPfUU3/72t2fcLv1Y6SLTDNc/Wyyxs0LRaudk0/LBTC6n2ZivtUhVVc6ePcvZs2fZtGkTq1atmvYaWJYdi+kw04Q9k6VJEATy8/PJz89n9erVKIpCKBRieHiYvr4+WltbdcuQ9s+o0hJmsn6lYwbLzmhyOMOio6GicjF+jtHkMIX2IkOPWV9fjyAINDc3c9ddd2W9ffr3KYoiu3btoq2tbcbPV1RUEAgE9L8VRWF4eBhArze1klh+W6BF1mhByIlEIqveVitF7Mxnn/F4nF/96ldcvHiR66+/npqamhmvgdGutpUgdlbCGJcTs12b+Y5Hq99TV1fHzp07ufnmm9m4cSN2u50LFy7w+uuv8+abb9La2srAwMCirK6W2JmZUGpkUe8vBL/fz+23384zzzzD+Pj4lPdHRuZ/TFVVOXbsGJWVlTN+5oYbbuDQoUMkEglgImbn8OHDVFVVZbi3VgqW2FlhTFc7Z74T0kpJPZ9LnASDQQ4fPozdbqexsZGCgoI5x2jk4paLc84FZlvQzYaZFvKFCgtJkiguLmb9+vVcd9113HTTTdTV1enB+ocOHeJXv/oVHR0dBIPBrH7/ZgsE1jCD2Cmw+Rb1/kLZv38/sizT0NDAT3/6U9ra2mhububJJ5/kxhtvnHG7Rx55hIMHD9LZ2UlTUxN/9Ed/RFNTE3/8x3+sf+app57itttu0//+6Ec/itPp5L777uPkyZP8+7//O9/5znfYt2+fqX4788VyY60QZqqdkw0rybIz3UKd7rbauHHjrNacdK5Uy46ZMNt4zPb9GWVFsdvtlJWVUVZWBkzUm9LifZqbm0kmk3qmV1FR0ayZXmaJjZmMGcROob2IVc41XIyfRyWtrQICVc7VhruwNOrq6jh69Chf//rX+exnP0tvby+lpaXs3LmT/fv3z7jdyMgIn/70p+nv76ewsJCrr76a//qv/2L37t36ZwYHBzl79uylcyws5KWXXuLBBx/k+uuvp6CggD/8wz9k3759OTm3XGOJnRXAbLVzsmEliZ3J+0wkEhw/fpzx8XF2796dVZFAURRJJpOGjW8liB0w34JuMTO5chm5XC4qKyuprKxEVVUikYgufs6fP4+qqhnxPumZXmZ1Y5nF4nRLyW/yX4P/nhG7U26r5jdKfjOnx62srOSJJ57giSeemPc23/rWt/jqV7+akaU6mYcffpiHH34447Xt27fz6quvAtDd3W3KgPX5YokdkzNX7ZxsWCliZ7IlZnh4mKamJnw+H42NjfMuipW+vystQHmlTkhLiZmu0VIIC0EQ8Hq9eL1eVq1ahaqqjI2NMTw8zNDQEB0dHdhsNl34aG5ys2EGyw6AU3TxvrL/odfZ8Yr52BNOnOLMVYmXCyPmK1mWcTgcBoxmebDEjklJr52jPcksdjLMVep5rtxYqqrS2dlJR0cHGzZsYPXq1Qu6BleiGwssy85smPHaLLX4EgSBgoICCgoKWLNmDYqi6G0tent7GR0dRRAEzpw5owsgMyx2ZnOvFdqLKLQXIcsy0WR0uYczI4u9ZoqimKKy90KxxI4JURSFVCq1aLfVZCRJMtSdA7kTO8lkkrfffptwOJy122q6/VmWHYvJmOkamcFllF6/B6Cvr4/29nYkSeLcuXOcOnWKvLw8/TM+n2/RjXUXwkpfdJcDI+Yrs1jUFooldkyEVjtnYGCAjo4Orr32WkMnwJXixkokEgQCAUpKShbktprMSnBjhUIhLl68qFfKNWIRMbsgW07Mdm3MIHYmIwgCDodDr7CbSCQYGRkhGAzS1tZGLBajoKBAFz+FhYVLshgqirLoOSEXmPE7TMcIy44ldiwWTbrbSlEUwuGw4T8cs4sdVVXp6upicHCQoqIirr76akOugZkrKKuqqnfCLi4upqOjg2g0SkFBgd48ciG9kcw86VpMxWziC6Yu3g6HIyPTK72tRU9PD6lUisLCQvx+v57plYv70CwByisJoyw7K9miZokdE6BVQpZlGUEQsNlshsfWgLnFTiKR4MSJE4yNjVFRUYHD4TBsojTaEmPUOcuyzOnTpxkYGGDnzp3k5eUhiqK+iASDQb03ktYXqaioCI/HY4kZAzDTNTSjVWCuMbndbtxuN1VVVXqmVzAYZHh4mHPnJjKU0jO9jLpvzWphMON3mM5ixybLsimv+3yxxM4yMlPtnFw07ATzFhUcGRmhqamJgoIC9uzZw9mzZw3tt2XGAOVIJMI777yDJEk0NjbicDj0eKrJi0g4HCYYDDIwMEB7ezt2u123+swUNLoS4oqWE7NdGzMulNmIivRMr5qaGt06nX7faple2n3rci0sa8lsAcorASPuL8uyY7EgZqudo2VNGT0Bms2yo6oq586do62tjfXr11NbW6unuxptiTFTzE5/fz/Hjx+nurqajRs3ZlzDyd95em+kNWvWIMsyIyMj+tOzFjSqiZ/CwsIVPSEtJWZaMM0odhYzJlEU9Uyv2tpaZFkmFAoRDAa5ePEiZ86cweVy6cKnqKho3nE4ZrbsmBUrQNkSO8uC1vJhpto52mKVC7FjFstOMpnkxIkThEIhrrvuOnw+36L3ORNmseyoqkpbWxvnzp1j27ZtU/rSzOf71toDFBcXAxPuv2AwSDAYzKiQm5eXh6IoplxELaZixu/JyNgYSZIyMr1SqZQe7NzZ2cnJkyd10a5les0k2s286JrtO0zHsuxYLBma20rrVD5TSrl2QxntI82Feyy9Js58f0yjo6M0NTWRl5enu3Am79PIcZrBspNIJDh27BixWIwbbrhh1kqm2eBwOKioqKCioiIjbmJgYABFUfjlL3+puw78fv+CXQeXG2Z8CjfbQplLd5HNZqOkpISSkhJg4vehxam1tLQQj8f1TC+/309BQYE+F5pV7JjxntJY7Ni0ByczXvf5snJHvsLQ3FZaXMZstXO0G8osVpi59gnMa79attVbb73F6tWr2blz55LEmyz3/kZGRjh8+DA2m42GhgbDhM5049JiJjZt2oQgCGzfvh2Px0NPTw9HjhzhjTfeMKQj9kIw22JgJnFhtmsDS2ttcjgclJeXs3nzZhobG7nhhhuorKwkEolw4sQJDh06RFNTE+fPn9ebIJuRpRhXIBDgU5/6FPX19Xg8Hmpra7nrrrs4ePDgrNuNjo7y4IMPsmrVKrxeL9u2beM//uM/Zt3mxIkT3HLLLRQUFPCBD3yARx991JT36nywLDtLQLo1Zz69RTQhZKb4mtn2CXObOJPJJCdPnmR0dJRdu3bp5uylGOdyubFUVeXChQu0tLRkxCQtFYIg4PP58Pl8rF27llQqpT89G5XivlIx24Rtxqfm5XStTQ7SHx8f1+/dSCRCc3MzfX19utvL7XYvuwBainuqq6uLm2++GZ/Pxze+8Q22b99OMpnkwIEDfPKTn+TUqVPTbhePx7nzzjspLy/nn//5n1m1ahUXLlyY9cErFArxvve9j/e85z0cOnSIn//85/zFX/wF+fn5PPTQQ7k6xZxhiZ0ckl47B8iqiZqZ4mvm2ifMbtnR3FZer3dat1Wux7kcbixZljl16hRDQ0Nce+21+P1+w44/H6Ybo81mo7S0lNLSUoBZU9z9fr8pFhDDUFWYdC5mOjeziS8wj7tIEATy8vLIy8ujpqaGw4cPU1NTgyzL9PX10draisPh0GOC/H4/Tqdz2caaSz7xiU8gCAJHjhzB6/Xqr2/dupV77713xu3+8R//keHhYV5//XU9EHzNmjWzHuv5558nFovx/e9/Xxfjsizz+OOPs2/fPlP9fuaDJXZyhFY7R1u0s500chFfk6vUc5he7Kiqyvnz52ltbWXdunXU1dXN6weSC7eT0eJptv2Nj4/zzjvvYLfbaWhomFeczHJMHEakuJsaVUUIRhEHxyGRQnXaUEu8qEXu5R7ZFMwaoGy2McHEuPLz8/H5fHqml9bTSyvQ6fF4dOHj8/lyWnE50dVF8sIF5LIynLW1OTtOMBjk5Zdf5mtf+1qG0NFIT/KYzL//+79z/fXX8+CDD/Iv//IvlJaW8j//5//kc5/73IwW+TfeeIObb74Zp9PJ+Pg4oihyxx138IUvfIGuri7q6uqMOrUlwRI7BqO1fFhsp/KVYtnRrFWT95tMJjl16hTDw8Nzuq1yPc6ltOz09fVx4sQJVq1axYYNG7ISuUYuLNkKxssxxV3oCyP2jk1YdSQRIZxAGE+iyIrpLClmFBZmdK3BVIuTJEn6fblu3TqSyaR+73Z0dBCJRMjPz9fFz2L67KUjj4zS+7nPEXn9df01V0MD1X/1LSSDjpFOe3s7qqqyadOmrLft6uritdde4+677+Zf//VfaW9v58EHHySVSvHlL3952m0CgQC174o37ZprVuFAIGCJnSuZ2WrnZEsuCwDmun7P6Ogox44dw+PxsGfPnqwtAmZu7zDT/hRFoa2tjfPnz7N9+3YqKioMO95iWOh3Pd8Ud22RycvLM9dinZIRB8ZBAFzaU70E8RRiXxiJ+buUlwqzjcesxfvmEmF2uz3DXRuPx/W2Fs3NzSQSCXw+H4WFhYuqZ9b7uc8ReeONjNdib71J72c/x6q/+9us9zcX2pyzkLEqikJpaSnf+c53kCSJa6+9lp6eHv7qr/5qRrGTfqzJMZlmvC/mwhI7BpHe8sGILuW5cmNBbur3aCJKC8hdu3Yta9euXdBxzNreQWPy+OLxOMeOHSORSNDQ0EBeXp5hx1ooRk9GM6W4Dw8P09XVpXfMNiTFXbu2izgHIZpCSMmojklTnE2EpIJbMFcjScuyM3+yjSVyOp0Z9240GmVoaIhEIkE8HtcXcpvNhiRJ87JYJrq6Miw6OrJC5PXXSZw7h2OOmJhsqa+vRxAEmpubueuuu7Latry8HKfTmXFumzZtIhAIkEgkpn0graioIBAIAJfKoPT39+v7W2lYYmeRzNTyYbHkyo0FxtfvEUVRryMzPDy86IDclWTZGR4epqmpiaKiInbu3GlIt3IjycUiKggCHo+HZDKJ2+1m06ZNuvjp6emhpaUFt9udUR13XigqwuA44tA4JBVUjwO1zItakL1wUiUBVRDeFU5p5//un7KahdUinkIMjCEMR0EQUP1ulMp8sBnnxjOj2DFjd3EtTGCh10q7d202G4FAAI/Hg91u1+fweDyut+zRBNB0c2XywoVZj5M8f95wseP3+7n99tt55plnePDBB6fE7YyMjMwYt3PDDTfwwgsvZAjFtrY2KisrZ7S833DDDXzpS1/KKIB74MABqqqqdPfWSsJ8sn0FkV47Z7YigQshVwUAYX41cbLl5MmTJJNJGhsbF515tBJSzxVFoauri1/96lesXbuWq666ylRCJ5cLZzAY5F//9V/5yU9+wosvvshPfvIT+vr6WLt2Lbt27eKmm25i3bp1qKpKR0cHhw4dIhaLEQgEGB0dnf67UFXE7lHE7lGIyaCCMBpD7AwijMYyP5tSEIajCAPjCKEYKNMIWbcd1WNHiMuX3ldUhEQKxesgyjxrDCVkpOZ+xN4xhFgKIZpEvBhCOjMAsnH3lNliiMCcAky7TkYXW3U4HHg8HvLy8nC73YiiSCqVYnx8nHA4TCwWy0g4sdfUzLpP++rVho0vnf379yPLMg0NDfz0pz+lra2N5uZmnnzySW688cYZt7v33nsZGhriT//0T2ltbeXf//3f+cY3vsH/+l//S//MU089xW233ab//dGPfhSn08l9993H6dOn+dnPfsajjz66IjOxwLLsLBitds7PfvYzGhsbp42OXwy5sOyk+1+NQFVVuru7icfjVFVVsX37dkN+BLlwYxm5P1VVGRwcpL+/P+vg66XG6EU0Fovx8ssvMzIygsvlQhRFxsbGOHToEE6nk9ra2mlT3H/9618Tj8c5fvz49CnusRRCMAKSCPZ3LSY2EeIphMAYaoFzwq0VSSB2jyLE3hUrAqheJ0pN4aXtAAQBpcaH0BVEiKY0gw6q14FcXQAX5icIxb4JkYNNvORWU9SJYOfBcdTy7ApEKuMpkieDpLrHEZwS9k0+bOvyTSsszDamhWa3zpd0qw5cstzLspxh4ZAqKnA3NhJ9801In6clCc8NNxhu1dGoq6vj6NGjfP3rX+ezn/0svb29lJaWsnPnTvbv3z/jdqtWreI//uM/+MxnPsM111xDdXU1Dz74IJ/73Of0zwwODnL27Fn978LCQl566SUefPBB3v/+91NQUMC+ffvYt29fTs4t11hiJ0umq52Tqw7lucicMirwOZVK6XVk3G43FRUVhk2MubDsgDGTdzgc5uLFi4iiSGNj47LV85gLIxcpVVXp7e0lEAjQ09NDMBgkPz9fXxC8Xi/hcJiTJ09Oa952u93Y7XbWrFmD3++fNsW9Nq+E6rgLweu4ZG4WBLCJE2IjpYAkIl4MIcRSqG77xPuKgjAWR+wLo6yalAHjtiNvKJ2wDCXevedtIuJYnELBObHPOWLndatS+vUUBZBBHImhCAJCSkEpcELe7PeCEkow/n/OoowkdHdaqmUU+85i1FLzBQObMWYn12JnMoIgYLPZsNlsOJ1Off6XZRnfI19F+dKXiL/xpv559/XXU/m/H8vpmCorK3niiSd44okn5vV57YHnhhtu4PDhwzN+7uGHH+bhhx/OeG379u28+uqr9PT0IMvyinRfaVhiJwsm184xUjxMJheWHW2/ixUSY2NjNDU14XQ62bNnD2+//faS1rHJlpkyCrIlEAhw4sQJCgoKcLlcphU66SzWsqOqKseOHaO1tRVZlhkbGyORSDA+Pk5eXp7uurXZbASDwTn3N1OKeyIwQiKZZDwYRpJsOBx27A4HdlVEkMQJgRFJTAgdl/2S+BBFVLuEMBaDVN7UOBpJRPV7EEIxhLE4qqygAkWCC2k4BnZ7pkVoMuIMAuTd+CLbwDgqIAGK34O8qXTGbeKH+1GGE+CSEN79jJqQSb4zhG03CPnmEjtmzMbKhRsrGwRBwG63Y7fbcVVW4v3ud4mdPUusqwuhsgrb6hrikoQUj+vxPma5hosZhyzLpi81MReW2JkH6bVzJrd8yJXYyYVlBxYnJFRV5eLFizQ3N1NbW8v69esRBMH0AcXaxLjQfSqKQktLCxcvXmTHjh2Mj48zNjZm2PhygVETrGZ9cTqdekXlSCSiZ7K43RMF+lKplN7UMRu0FHd8RUhn+nHFXMSFCRfx+FgYpyoSdKRIdMcpc+aTp6oZ8cbAu5YWdfrYHYCkDOMJVM1FpiiMq0mElIIwnkD1zVxkUCn2IIXioCigLbApOeNY2nCEYATx/AhK7VS3pqqqJNtGQRJ0oQOAXUSNybj6VYTV5lgUNczqxsqmEn2uEUURz/r1eNavZ2xsDLfbjaIoyLJMJBIByMjyWg7BsJiUdQ0zBqtniyV25mBy7ZzJP7RcWmDMZNlJpVKcPn2awcFBrrnmmoyFLRdFAHNl2cmWWCzGsWPHSCaTNDQ04PV66ezsNGVA6XQsdpz9/f0kEgkKCgoAyM/Pz0jbdTqdxGIxRFFky5YtCz+QJKLU+BDPj+CKC7jsNrBD0iWieJKMjo7QM3yeTWIx9ogDm8cxkUorSghJecKtNZOFJqkgyCqq6904DNKESl8YYSgCThuK3w2eTL+WWpqHOhKbyMTSfo/vCp3JS4cAiIExlDW+6dPmZ/sqVPPVLjFLu4h0zDimdERRzEhU0OJ9Jmd6aQLIzOeSjtmv+3ywxM4szKd2Tq4sMJIkkUgkcrLfbEVUutuqsbFxSg2VXFU8NurJcqGWnWAwSFNTEyUlJezatUt/KjPa8pQLjFo4J5+n3W6nurqaCxcuIMsy4+PjOJ1OrrrqKurr6xd3rAIX8sZ3Y2xSCrjtiPlOqkWBalajKArxcwNIAxGSYzGGh8dwSjZEh41EgRevLE+fETfNpXBjw94/jiCrE5YhAYSBMMqaIlS/59IHRQF5Q8lE9tdoDAQBIZqcCKae5hYQUooej5PxuiBgW19A8tQwqqJesu4kJ/4/WqKSZzKxY2bLzkpBs+Y4HI6MYOdkMkksFtNdwJoAysW5GfE9LjYEwAxYYmcasqmdc7m7sbReM7W1taxbt25adZ8LsQPGTbbpAcrzQVVVurq6aG9vZ+PGjdTU1GSMI1diJxf7Xez+SktLsdlsxGIxXeQ6nU78fj+1tbVUV1dTVlaGx+OZY0/zxC6hlkyf2SiKIu7aMgRfFFcwSl4iRVRN0aeM09vbRfRs8/Rd3B0Sql2EuAxOCVSVCsmLkFJQnbYJi5CqQkJGvDCKXOiayArTEARUv0cXQUJ/GNtQZMr4VAC3bcaYHWdDGfKFMEooiap/RMC+vYh44SD5JlvEzSp2zGhhmI+rKD3YWdtGW2cSiYRuIU23/Jjl+pv1umeDJXYmkW3Lh8s1QHk2t9VkclHHBoz7gWXjxkqlUpw4cYLR0VGuu+66aYt0XUmWnfLycurq6vQeQ9p3XVFRwc6dO/WYnSVDEFCLPKhFHlBVXILAGmANs3dxL/YW4lZBjKUgnsQt2FFt4kRK+bv7xT7hEhPG4rPG8aglHtRztom0eO01Jow5qdW+GbeTipx4P7qOxLEgqfNhBLeEY3MRto2FqMcHjbk+BmLGBc6MY1oo04kfLdMrFouhqmpGrM9CxY8RotXoQrTLgSV20tDMi9lUQl6Jlp25xhsOh2lqasJut0/rtppun7mw7Cx1M9CxsTHeeecd3G43jY2NM1YWXQlixygEQeDaa6+lrKyMnp4eUqkU5eXlrFmzZvmz0Sb9Pufq4u6yOSgr9ONzeslTFVTbpN+4wIRqmeurFUVSOyqQ2gZhJDYheOwiqTVFqKWztwoRCxy4bpraN01VVMRRmWQshOi1IZa7l/2p3oyWHTOmw4MxQcDpmV6AHuicSqX05Jhs21qkj20xWG6sy4T02jnZVkJeaZaduUTUxYsXOX36NGvWrGH9+vXzmlhWgtiZS6D09PRw6tSpjCyzhe7LLMTjcdrb27HZbBQXF+P3+xc0GYuiyJo1a1hjQKE0beJ2uVw5XUhn6+LeNtjDBjUPaTyGbJ9YYCSbbSLQ2S6i5s+jca3ThrytYiLTK6WAy7bgXl5qTMZ/ClzhEFE1jGATkSrcuG6pQsxfvgwYM4qdy8myMxeiKCKKYob40Sw/8XgcICPeZ7brYkTMzkq/7le82Em/gSD7TuUr0bIz3X5lWeb06dP09/dz9dVX69VvF7PPhZJtjM18mGmMiqJw5swZenp6uOqqqygrK1vwvsyCqqp6qnwoFEIQBBwOB3V1dWzfvj2nk5aqqpw9e5ZTp04xOjpKUVER27dvJ5VK8frrr9PR0YGiKBQUFHDjjTeyefPmnI0lnfQu7qtXr+bk67/iancetqRMKhkjpYIgiowWSTiikfl3cbdLs9fpmQexI314BkHNA9HrgKRCqnuc2Ku9uD9YM+M41KSCfHEcNakglbsRC+Yh0rLAjFYUswYoL8XDjyiKurVZK4eiPaTPlulllGXHbPdCtlyxYme22jnZkEuxs1QxO5rbymazsWfPnqw7Vudi8V+K2j2xWIympiYURaGxsXHeQbZmt+wMDg7S0tKCIAgUFRXpAcbt7e0UFxezatWqnB37xIkTHDlyRDd7axWntQlZu26hUIj/+I//AFgywZPOiBpD2FKONBTFNp4gKUFQjNMbHWH47XOIoqg3Ml10F/dZUMaTpDrHkG0qkuPdmAyHhKiCHIigDMaRSqceO3U+TOznPShjyYkCh04J+1V+nDeUGSYGzCgszLzoLuW1mk9bCy0myIjCopdDUUFz3jU5RnNbJRKJRQkdyN1T/lLV7+np6eHIkSOUlpaye/fuBU3qK0XspO9vaGiIw4cP4/V6uf7667PKJjK72AkEAiQSCex2u35vu91uVFWlp6cnZ8eNxWL8+te/BiZaSLhcLr07uhZwOZlf/vKXS34tteOpHgfKmiKULeVIG8sprV/Njh07uOmmm9i+fTtut1v/fbzxxhu0trYyMDCgt4oxZCwRGVIqqjQpW90uTrwemXosZSxJ9EA3ymgSwWNDKLCjKiqJXw2SbB4xbmwmteyYbUywtI1cA4EAn/rUp6ivr8fj8VBbW8uHPvQhfvGLX+B0OvF6veTl5elzuSzLvP/979eDodP/3XnnnbMe68SJE/zGb/wGN954I+vWreORRx4x9dw3G1ecZSe9do5W/XcxSJJk6OSXvt9c9tySZZnm5mb6+vrm7b6ZiVyInVw1A1VVlc7OTjo6Oti8efOCrBxmFzupVGpa8S6KIslkctptwuEwPT09RCIRPB4PVVVV5OXNHmw7mYGBAeLxeIZgnutBIhQKEYvFlj6ri5mfxEVRxOfz4fP5WLt2LalUSs/y6ujoIBqNTp/ivgDEAjuCU0KMkqF21LgMDhHRN9U1lWoPoY7LCAWX6rIIHhtKKEny5DCOLcY0prUsO9mxFNeqq6uLm2++GZ/Pxze+8Q22b99OMpnkwIEDfPKTn+TUqVP6WDRBE4/Hef7551EURXd9DQ0NcdNNN3HXXXfNWEcuFArxvve9j5tvvplnn30Wm83Gfffdh9fr5aGHHsr5uRrNFSN2sqmdkw3LmTW10P3G43HeeOMNJEmisbFx0QvNSrHsJJNJ3nnnHcbGxti9ezeFhYVzbzjDvswsdoqKinRLljZObZKbLhZrcHCQt99+m3A4rF/3rq4udu7cmVULCC01dvKCNNvvLD0Ac6nI9rubrov7TCnuehf3ec4tglPCvsWH+MsxGJdRPQpqUkZNKNg3+xALp4odZTwJTBM8bBMm3FoGYcYAZTNamxgdQQgOI7pd4J2+RpRRfOITn0AQBI4cOYI37Vhbt27l3nvvnXYbVVUpKSnJyJ7813/9VzweDx/60IeIRqPTZno9//zzxGIx/vZv/5aOjg6uvfZa2tvbefzxx9m3b9+87o3e3l6Gh4f1GkJ5eXlT5iBVVfnqV7/K3/3d3zE8PMz111/PU089xdatW/XPvOc97+EXv/hFxnYf+chH+PGPfzyv6wZXiNjJtnZONqy0AOVIJMLAwABr1qxhw4YNhkwcK0HsqKrK6dOnKSgooKGhYca08vmQS7GzkAVGURSi0ajurqqurub8+fMEg0HGxsb0mJ2SkhJqamqmbHv69GkikQglJSX6uQWDQU6fPs2NN94473ukvLycgoICRkZGMoTPTNdKEAS2bNkyfdXjJWChc8BcKe52u10XPkVFRXPea45rSwie66IsJKEmZAS7iH1LEc7rpk8SEP3OiXpDsoogpQXzJxWkVcYttmYUO6ay7MRiiK/+HKG7GwlwAOqqVSi33Ao5KMsQDAZ5+eWX+drXvpYhdDSmqwk2E88++ywf+chH9IeZ6dpa/Nd//RfXX399xjW/4447+PznP09XVxd1dXVzHmdsbIyysjK8Xq/eW7GrqyvjN//YY4/x+OOP8+yzz7Jhwwb+4i/+gttuu42Wlhby8/P1z/3RH/0RjzzyiP53tg/pl73YURSF0dFRjh07xg033GD4jzfXqedGTTiyLHPmzBkGBwcpKipi06ZNBoxyArO7sS5evEg0GqWyspIdO3Ys+nqaybIzPDxMIBDQr7/NZqO6uprrr7+egYEBPB4PkiSxbt061q5dO2WCCIVCjI6Okp+ff8kl8m7a9ujoKKFQaN6TqCRJ7N27lwMHDuhNEGGin1ZlZSXnzp3TJ05FUSgvL2fv3r3GXIgsMPK7my3F/dy5c5w6dYq8vDxd/BQWFk4J9BREgeFVMiW1JXidBRNxOM6Zg0Ht6wpIvD2IMhgHtzQhfGIpsIs4rio27NxMJSzexUyuNfHVn8PFi5kvXryI+F8HUd73AcOP197ejqqqWc/dk61hb731FidPnuTv/u7v9Ncmt7VQFIWBgQHKysro6uoCJlxomhU2EAjMS+xs2LAh4+/a2lqOHTumz1eqqvLtb3+bL37xi/z3//7fAfjBD35AeXk5zz//PH/yJ3+ib+vxeKiomFqjar5ctmJHc1tp2Vajo6M5OU4uLTtgzNPV+Pg4TU1NiKJIbW1txkJkBGa17CiKQnNzM4FAAI/HQ3l5uWHtJ8wgdrQ4m3RSqRTnzp1j/fr1ek+v6Z4CNWYqhrbQ9P+qqio+/OEP097eztjYGIWFhaxfv54TJ06we/duBgYGdOFZW1trmoXLKNJT3AESiQTBYJBgMEhzczPJZJLCwkJd/Ggp7qqqIjgkxKK5LQKCU8LzwdXEDgWQuyOoqoLod+G8vhTbmuzirGbDsuzMwugIQnf3lJcFVYXubhgdhQW6yWdioYULJ/+G/+Ef/oFt27axe/fuaT+vZXo5HA6Kioqoq6uju7sbu93O4OBEpe+zZ8+yatWqKZbiuUj3rgB0dnYSCAS4/fbb9c84nU727t3L4cOHM8TOc889xz/90z9RXl7O+9//fh5++OEMy89cXJZiZ7LbSjOZyTM1ClwEuRY7iy3THQgEOHnyJKtWrWLDhg1cuHCBcDhs1DABc4qdaDRKU1MTqqrS2NjIsWPHDBMoZqmzo0080xEMBoG5xUpBQQH5+fmMjIzoRQdVVdWFitbtPBvy8vK4+uqrp7zucrm45pprst5fLliqRdzhcFBRUUFFRQWqqhKJRAgGgwwPD9PV1aWnuCeTyRmDxzVUVUUNp/S4HNfNlRM9tmQVsdBxqbmoAWj3jSmERRqmETuh0BzvGy926uvrEQSB5uZm7rrrrqy21e73SCTCP//zP/OVr3xlzm0qKioIBAJ6PM+qVasYGBgAJmKEsg0FUFWVCxcu4PF49PEEAgFgwgWeTnl5OefOndP//tjHPkZdXR0VFRWcPHmSz3/+8xw7doxXXnll3se/7MTOdC0fNNNbLsROLgOJYeFVhNOL5W3fvl2/mcwoTKZjMdaTwcFBjh07RkVFBZs3b9bvA6PEjlksO4lEYsb3NL/7XEiSxObNm3n77bcZHBzEZrORSqVwu91s3rzZsNoaZrIQLNd3JwgCXq8Xr9dLTU0NiqIQCoUIBoPIssypU6fo7OzUY320GknamOXeCHJPBDU50dNCEAXEcje21XmGCh24NO+Y6XsDEwUoz/UQUGCs0AHw+/3cfvvtPPPMMzz44INTLLYjIyPTupzT7/f/+3//L/F4nI997GNzHu+GG27gS1/6kh5cDHDgwAGqqqq46qqrsr43zp8/TzQapba2louT3H+T9zXZqvhHf/RH+v9v27aN+vp6du3axdtvv83OnTvndXwT3DXGoFlztNo56UHIWvprLkSJzWbLWTbWQscciUR44403GB0dpbGxMUM158ISZRYBpaoq7e3tvPPOO2zatImtW7fqP1Ijx2gWsTPbk5WWeTGfcZaXl9PQ0MDGjRspLy9nw4YNNDQ0THnaupwwwyKupbivXbsWh8PB1Vdfzbp161BVlY6ODg4dOsSvf/1rOjs7CfUESXaPIzhEpGInUrELIc+O3BdFGY4bPrZsXSaqohAPjxEdHiI+FkLNkeXTNJadQh/qqlWokxdpQUBdtcpwq47G/v37kWWZhoYGfvrTn9LW1kZzczNPPvkkN95444zbad/j97//fe666y7dzZrOU089xW233ab//dGPfhSn08mDDz5Ie3s7L774Io8++ui8M7HSOX/+PKOjo2zcuDFj3tJicDQLj0Z/f/+s88/OnTux2+20tbXNewyXhWVHq52jLWaTfwyaDzJXFphc1NnR9p3tmDW3VXV1NRs3bpxyLcwiTIzeZyKR4MSJE4yPj3P99ddPcb9cjpad4uJixsfHp31PSz+fL1pdmSsBM3x3k1FVFZvNht/vnzbFfai5B8+wiL3UQ15+Hvl5+TicDgQBlNEEUvH8i4GqqorcEyF1dgwkAfuGQqQS15TPwPzcWHIiQainm3g4NPFEDjjyCiioWoXN4KwkMwUoK7fcivhfBydidDSqqyeysXJEXV0dR48e5etf/zqf/exn6e3tpbS0lJ07d7J///5pt9G+y9bWVl5//XX+8z//c9rPDQ4OcvbsWf3vwsJCXnrpJT7+8Y/z4Q9/GL/fz759+9i3b9+8x6u5roaHh9m4cSNOp5NYLJZxPhUVFbzyyiu6izuRSPCLX/yCb37zmzPu99SpUySTSSorK+c9lhUtdtJbPsxVOyeXxf+0cRj9xJFN+rmiKHo/pG3bts0YtW4GYTIfJlc8no3R0VGamprIy8ujoaFh2rot2exvPmMzw4KZn59PRUUFfX19GYtTdXW1XtjPDOO0mJvpgoHTU9xTReOMtw0RtscJjYbo7e3FJtkoFL14hAIKimwIF2KoSQVbtWfGrumqohL9t/MkT4/or8VfC+C8sRzXjZfmjGzcWOH+ANHRYZz5+YiSDUWWiYdGCEsihTXGBqGbxrID4HROZF2NjpIcHEQtKMCRRU/BhVJZWckTTzzBE088Me9tBEFgw4YNs66BDz/8MA8//HDGa9u3b+cnP/kJiUSCtWvXZj1WrQTG+vXrkSRJj01Ltxx++tOf5tFHH6W+vp76+noeffRRPB4Pd999NwAdHR0899xzfOADH6CkpITTp0/z0EMPcc0117Bnz555j2XFip1sa+fkOpA4Fz/C+Vp2IpGIHoA7V4+nlSJ2tIrHc9Hd3U1zczNr165l7dq1s1bFNbNlZ6EtS4qLi/H5fEQiEQRBwOPx6PehWZ6AzYjZrs1cmU9inh2X24U7L5+y0jIURWE8FCbaN8Zw1wC8OoikTMyBgiRi3+TD874avQ6PRrJpiOSpkYlqzdp0pUD8l33YavL0bK75urHkRIJ4eBS7x4MoTSwnoiRh9+YRD48hx2PYXMZVxzaV2NEoLCTlcJhvXO+y2Kw6rc/dQtACmltaWqaMSeNzn/sc0WiU+++/Xy8qeODAAT3TyuFwcPDgQf7mb/6GcDhMTU0Nv/mbv8nDDz+c1bhWpNhJb/kw3wKBNpst51lTucj0mktE9PX1ceLECaqqqti0adOcP7jLJWZHa3fR39/Pzp07p/VBp3M5urE0JEmaMQXTDOPU2nSYBTONRWOuMQn5dsRyN3JfFEEABAGP7MBbXUb+oQCqoKC4JuZGNZlCPjFIIDGEbWdminvi+ESWHukiSFRBgeSp4QyxMx8BrigyqqwgTer8Lkgi6rvtCYzElGLnXcwmoI1iMWJn165dU16LxWJ0dnbqfwuCwFe+8pUZM8RqamqmVE9eCCtK7Cym5UMuY3ZyFfw825jn67aazEqx7MzmdopEIjQ1NSEIAo2NjfNqXno5BijPxXJPvoqiTMSbDA3R19eH2+3G5XJl3XMrFyz3tZnMXE/fgihgW52HmG9HGU1MpJv7HCRbR1GTCoJLwqbVRnKAGk3h6xe4ODqakeJeNaYgopLRiEsQQFVQ0pqOzjc2RrI7kJxOUvEYDtul71WOx5EcDmwO42N2zCh2zDofLLQ2TzqKoix5S5dcsGLEzmJbPuQqZkfbd66E1HQLtOa2UhSFhoaGWYvGzXefi2Ep3VgDAwMcP36cysrKeVmyNIwUKOlNRc22aE4m/ZxVVaUrmqQjkiSmqPjtIhu9ToodxqSXTz5uT08Pvb29+kQ5PDxMZ2cndXV1yyp4zLgwzedeEkQBqdiVEYycPDE88V7atgKAKGBPSezYsSUjxX0sf4T8MQE1JSOIE5YbYWIH2NJaTcz33hYlCW9xGaGeC8THQkgOB3IyCapKfmU1osHWbtOknk+D2eeChSLLsmElKJaTFSF2pqudky25EiS53Pd0++3v7+fEiRNUVFSwadOmrG/CXAkTMPapa/I4tbTyrq4utm7dSlVVVVb7MzpAWRuTkROc0ZPl5P01heJ0RC8VruuNy/TGI+wpclPhNHYqiEajDA4O4vV6cTqd2O12CgoKiMfjDAwMmMK6YzYW8v2L5RPxMKqi6rV2VFVFVVRslROxe+ld3OX8GOEftqImFFQFVFVBBWQXDPvGKBp1kp+fn5WocPmKECSRaHCIVDyOw5OHu8iPq9CX9fnMhWXZyQ6jLDtmvObZYmqxo6oqqVRKt8gspoFnLsVOLgsLavtVFIXW1lYuXLjAtm3bskq5S0eLAzJyoc6F2EkXJ4lEgmPHjhGNRrnhhhuyKhGePkYjY3bAvBNcOtoYQyk5Q+gAaKM/FopRXuI1VGzFYjGSyeSU78rlcjE+Pr7sT4tmegpfjJXQvqGQxNEB5MHYRByOIKCmFAS7iHP31MwgqdRF3t3rif2il9S5MAgiwjovse0OwolRLhw/jqIo5OXloSgKkUhkzi7ugiDgKvDhKvBN1NdZYLD9fDBT6vlkzDguI+YoS+wsAVp8Diw8W0UjVwHKkLsO5dp+tdYHiqLQ2NiYldtqMunCxKjFZrHVnmfap9bT7J133qGwsJDGxsYFB4HnyrJjFPF4nBMnTgATGVZ+vz/rrr6TSf+99MVnvvfHZJWoouKRjJus07uep0+UsizjWObMFbOK1IXMb4JdxPM/6ogdCpBqC4GqIlV4cN1YnuGWSkeq9OD9n+tQU+8KE0mgAKikRu/ifvHiRUKhEG+99VZWXdyFHH+vZl14zXpPweJFmJFrxXJiarGjCRwjFPNKdGOJokgoFOLs2bOUl5cbUr5/pYgdQRAYHR2lu7ub9evXL7pppJHWN6PFzsjICO+88w5FRUW43W76+vpobW3F7XZnLDIL+b70+jtzXDqjlw+tLUIoFNILPCaTSQRBoKKiYtmfgpf7+Oks1tUg5tvxfKAGNalMWHVc0rz2JdimfuuCMNHFvaysjOHhYXbv3p11F/dcYlaxA+a6pzQsy84lVoTYMQJJkojHjS+rru3baLGjKApjY2OEw2G2b9+edYzKTGg3rSzLhkXYa9+RUWJHlmUGBgaIRCLs2rULv9+/6H0anXoOxkwkWp2g+vp6qqqqUBSFuro6UqmUXj23tbWVeDyOz+eb0i1bG0csFkNRFJxOp279Sv/tVDltNBFn8ogFwG8XcUnGTmY2m42amhouXLjA6Ogo0WiUWCzGmjVrKCkpMfRY2WK2p3Aj4ipgwsoj2I35HjW3WrZd3B2oJCLj2F1unAWFhgsAMwcomxXLsjOBqcWOkawky04sFqOpqYlYLEZlZaVhQgcuxT0ZbYUxKvB5fHycpqYmUqkUpaWlhggdMJ8bS1EUmpubCQQCep2g9K7XNpuN0tJSvXWA1i07GAzS1dWFJEn4/X4KCgoyOmZrKcZFRUUZY3RLIlflO2kaiyNwKV7HJsDOgvm3GsiGvLw86uvrCYfDhMNhamtrqampMeUT8HJiNvEFMwffT9fFfWhggJGuDoZ+dRhRSSGKEqLdjre4lFXXXo/9ci8qiPHJCkZhxL2l1bNb6Zj6DIy8eVaK2BkYGOD1118nLy+P6urqnCjq5ax4PBt9fX0cOXIEv9/P6tWrDf3+cxGgvNBrGIvFeOutt/RGrXMVRATweDysWrWKHTt2cNNNN7F161YcDsdEOvHYmB4QnEqlGBwcJBQKTbl+670OfqPYQ63bTqVTYkueg9tLvBTac/fUZrPZ8Pl8eDyeOQNdlxKzjAOMs+wYyXwsKIIg4JQkos1N0NeNTU4iqirIKVKJBCM93Zz42Uu0tLQwMDBgSOkPMwcoLxWBQIBPfepT1NfX4/F4qK2t5a677uLgwYPTfl67Xn/zN3/Dli1byMvLo7a2ln379mX0qZqO48eP84d/+IcUFxdTXV3NI488YkpxPh+uGMtOrgOUF7tvRVFob2/n3LlzbNmyherqajo6OkgkEgaN8hJmq7WjKAptbW2cP39ezzTr6uoy9EdltGVnoW6x4eFhmpqaKC4uZuvWrQsSs6IoUlRUhCiKBAIB/f5LpVLEYjFEUeT8+fMkk8kpk5nfLuEvXPkm6cVgtsnaTGJHVVXkc2HEpmHKxiRSJWNItXkzjq33+K+Jh8emvC4qMnavF0VOoUQjdHQME41GKSgo0F1e+fn5WVkMctWDcLEs5ffX1dXFzTffjM/n4xvf+Abbt28nmUxy4MABPvnJT3Lq1KkpYxMEgeeff54vfOEL/P3f/z0NDQ20trbyB3/wBwA8/vjj0x4rFArx/ve/n6uuuorvfe97dHZ2cs899+D1ennooYdyfq5Gc8WIHTNbdmKxGMeOHSOZTNLQ0KDXIMmFKNH2a5aWEfF4nGPHjhGPx3N67kZadmBhMUAXLlzgzJkzbNiwYVrLVbaTpea6kiQJSZJwOBx68U1FUZBlmdbWVs6fP58R6Gx0W5OViBmExWSWe0yqqhL9l/MkTw4jCVCIwPjzHdg2+/B8aI1exyf98yPnO2GG34EqKwjAqooyNldUZ3Rx7+7uRlEUioqKKCoqwu/34/F4Zr0G2XRiX0pG+iL0dY9SUSPhK5+5L6ERfOITn0AQBI4cOZKRlbt161buvffeKZ/Xrtkbb7xBY2MjH/3oRwGora3lIx/5CEePHp3xWM8//zyxWIyHH36YHTt2cM0119Da2srjjz/Ovn37lv1+zRZTz3pGu7FyVUF5MeJhcHCQ48ePU1payubNmzMWolwWKzSDZUezchQVFbFz586Mczda7Bjd4iGb/SmKwunTp+nv7+faa681LA7J4XDo49B+K9p/vV4vbrebNWvWIIoiw8PDdHR0EI1GMwJK8/PzV9yktVgsy870JE8Nkzz5bkVmFbSWEqnmEZLr8nFcNcndqqoTdXVmQJVlJIcTu2fiASa9i7uqqgx1n2ego5VgZwv9ioLsySdv1WqKS0qnTXHX5gOziJ3YeJKf/UMz3c3D777SwarNRdx232acHuPbKwSDQV5++WW+9rWvTVt+xOfzTbudIAjs2bOH5557jrfeeovdu3dz9uxZXnrpJX7v935vxuO98cYb3HjjjRmlIu644w4+//nP09XVRV1dnSHntVSYWuwYSa4tO9kKKUVR6OjooKuri82bN7Nq1aopn8llscLlFDuqqnL+/HlaW1upr69nzZo1Uyb6XIid5RBPsViMd955B4CGhoZF185Jx+v1YrfbSSQSel0bWZYRBAGfz0d/fz+xWAy3201JSQmrV69GVVU90PncuXN6QLP2z+k0tpeRxdyYRXwljg+TEb2uIUDieHCK2BFEEU9xCZGhoWk2mnglr7wCV0HhlPeiwUGCZ05AIoHb7UKRZeR4BLWvh3Ph8WlT3M1m2fnZPzRzsWU447WLLcO88v1mPviJHYYfr729HVVV2bRp07y30a7ZRz7yEQYGBti7d69erPfjH/84/9//9//NuG0gEGDVqlUZrvby8nL9PUvsGIxRT+RmcmNpbqtEIjFrReBcFStcTrGTSqU4deoUwWCQXbt26VlDkzHaErMcbizNclVSUsKWLVvmjM/J9slekiSqqqp0UaMoCjabDb/fjyRJGXFq8XicRCJBYWEh1dXVVFdXZ/RMunjxIs3NzRkLjM/nI6rAmDzxvebbRLwGp6gvB2bLnJlvh/GcE5en0yygghqf/rddsX0nZ3/xCqiZKkmQJHxr1lK57epptxs624YcT+BIK6EgJ5Mo8SjbrtqJLb9gSoq7Vq8pHA5TUFCwrNdrpC+SZtG5hKpAd/MwI/0RfGXGurQWagEUBIFXX32Vr3/96+zfv5/du3fT0dHBn/7pn1JRUcGXvvSlWbdPF5dmsUIuBNOLHaMwS4Cy5rYqKSnh2muvnTV+IleWnVwIv/lYTsLhME1NTdjtdhobG2e1Iqxky46qqly4cIGWlhY2btyY03Rrp9PJqlWrSCQSqKqqm/6HhoYAdNFjs9lIJBKMj4/jdDoRRTGjZ9LatWtJJpP6AnPq9GnGXXmI/lIklwuH3YHbbqPSaaPKZUMBwimFiKIgIuCVRLzSzAv2SpwclwqziC9bbT5yb2Ray46tbvpeZnllFay75Q76Th5jfLAf0W6noKqask07cM7wEKfIMrGRYaR33bAaos2GHI8RGx3GX1wyJcW9r6+PkZERmpqaMkos+P1+XK7clE+YidBgdPb3B6KGi536+noEQaC5uZm77rprXtto99bDDz/Mxz72MT0oefv27YyPj/Pxj3+cL3zhC9NayyoqKujr68t4r7+/H7hk4VlJXDFiR5KknEXzz0c8pDey3Lx5M9XV1XNOcJeTZScQCHDy5Elqamqor6+f8ztYCQHK040vV/E5c40lXTgmEglSqZTec0nDZrORSqVmrJtht9spLy+nvLyc4USK5lCUVCxGcnyMsViMMYeLYZeLqFPCkZ9PVBUQ3xV9oZRCkU2k2DG/6r3LjZnGaBY3luO6EhJNQ6jR1CXBI4DgknBeN7XPloa3pIy177lt3scRBAFBklAS0xd5ndwpXRAEvF4v5eXlnD9/nptuukm3SPb09NDS0pJRbdzn8+U8CL+gZHZ3dEGpce5qDb/fz+23384zzzzDgw8+OCVuZ2RkZNq4HUEQiEajU37z2po40/13ww038MUvflF3jQMcOHCAqqoqamtrDTmnpcT0NmkjKygDOQlSnkvsxONxjh49SiAQ4IYbbmDVqlXzOq9ctqFYKrGjKApnzpzh5MmTbNu2jY0bN85LbC5nQPFC9xeLxXjzzTcZGxujsbFxQULHiDHO1GYlG3fJaEpBlCRKfAVUVlayZk0t5UWFIIqcHR7lZPtZ+s51Eh4cQExEsQswkpKJKeZYuGfDLOJCwyyWHTHPTt699di3FqFKoIhg2+zDe+8GxIKZ+2FliyCKFFTXoMgySmoio1BVVZKRcWxOF3llmU2OVUUhPDTI2NCgXsBUs0bu2rWLm266iXXr1ukPlIcOHeLXv/41nZ2djI6O5uSB0VfuYdXmIoRJU5kgwqrNRYZbdTT279+PLMs0NDTw05/+lLa2Npqbm3nyySe58cYbp3xeu7d+8zd/k7/927/ln//5n+ns7OSVV17h4Ycf5s4779TXxqeeeorbbrskWj/60Y/icDj40pe+xMmTJ3nxxRd59NFHV2QmFlxhlh1gyd1CQ0NDHDt2jOLi4ikZR3ORy9TzpRA78XicpqYmPaU+mwamubDs5NJSFAwGaWpqoqysjC1btizIemjUImyz2TIytWBCdCaTSTwez7zuwZSa+aAhiAJuj4d8h4I9Px+voJAaDzMWDjM4OACAo7AI1eNkdXGR6QOdzTRZm0XsAIg+J5671hDYLhOPx9m8uTYnxyleu4F4aJTxwX54txaU5HRRvu1qbGkuqcHznbQcepXQQB+plExCsjFcv56iqmr9M5Orjc+U4q5ZfoxKErjtvs288v3mjNid6o0T2Vi5oq6ujqNHj/L1r3+dz372s/T29lJaWsrOnTvZv3//jNt98YtfRBAE/vzP/5yLFy9SWlrKBz/4Qb72ta/pnxkcHOTs2bP634WFhfyf//N/+OxnP6vHV+7bt499+/bl7PxyyRUjdrQngqUSO6qq0tHRQWdnJ5s2bZq3NWeu/RpBLvY7WUwEg0GOHTuG3++fMzZpPvtbLLmy7KRnluU6PiebsRUUFEwUiJNlvSecy+XS6xjNRb5NZCCRQlFVRK1itKqiquC2CdhEOwX+Yvz+YlRUopEIA+EIAwMDdLc04/F4MtwKFrOz3PfMZHItwCS7nVXX3kBkaIBYaBTRZiOvvDKjtUSov493/u3/ER0L4S0qQo0niPb28M6/v8gNv/O7eAp90+57cop7OBwmGAwyMDBAe3u73sXd5XItak5weux88BM7GOwJEewNU1bjy5lFJ53KykqeeOIJnnjiiTk/q32PNpuNP//zP+fP//zPZ/zsww8/zMMPP5zx2oYNG/jRj37E+vXrFz3u5cb0YsfIH1yugpQni6h4PM7x48eJRqNcf/31ehbBQvdr9MSTS8uOqqqcO3eOtra2RS3+uRAnRosnWZY5efIkg4ODs2aWLQc2m01vDFpYWIgoijidznl/F367xJBdYjQpYxcFVCClqPjsEmUOicGEjKyqSIKAgIDk8lDmdLNqVTmiLOtP1mfOnNG7nQ8MDOB2u/F6vcu6uFturLlZioabgijiLS3HWzp9sGt38wkioRGKqiYeFFVBwlnkZ2xogJ6W06zf3Tj3MYSJLu75+fmsWbMGWZYZGRkhGAwiyzKRSETPYtSKc2b7XRSWuvH4bHg8uRc62bLYe/1yaQIKK0DsGMlSFOnTLBpFRUVcc801iwqU026ylSJ2UqkUx44dY2RkhOuuu25RT/RmD1BWVZWWlhbsdjsNDQ1Lng0yH7QnusmTsKqqRBWVhKJiE4Rps6jsosB6j4P+eIrh1MRvpshho8xpwyZAUlUJpbTgRhVJgGK7hFMUQRQpKyujrKxMz6RpamoiHA7zq1/9Sn+y1v7Z7cYXYJsLM4kLM4odM/SgGuvvw2a/lLGloiIKIoIoMh4cWtA+tS7u+fn5BAIB3a2bSqVIJpOoqqpnMGriZy7MJp4ns5jv0YztORaKJXYM2m8qlaKjo4OzZ88a5s7QbjKju87mQuzIskx3dzcFBQU0NjZOqX6aLWZ2YwWDQSKRiO6iM/NkMPmcU4pKTzzFSHLCMiMKAvmSSLXbjnNSOwCHKLDKbWcVU8VImcNGnqQSf3dRdIsCLnHq/a5l0jgcDmpra/H7/YyOjurd20+dOqX3S9IWoVxfT7MtTmYbDyyNZWcuPD4/ckebLgZVVUVlog2FK39h1vLJCIKA3W7XBbeiKHrGYjweRxCEDPEz0zVZbmE4E5Zl5xKmFzsroWWE5mrq7u5elNtqMtpNZrQwkSRJj+Mwgt7eXvr6+sjPz2fXrl2GfGdmdGOlx+e4XC5qamqWfUGYjem+h75EisGEjEcSsIsiKVVlJKVALEmd2z7v704UBPJsAnlZJnRKkqRbdNavX088Htdr+xw/fhxVVXMSTDoZMy1OZrTsmGFM1Vu2cbH5BGMD/Xj9flLJBInQCAXlFVRt3JKTY4qiqD+oaaVKUqkUiURCt3Kkix+j56lcsJjvUZblRT+4mgXTix0jyYVlR3NbAVx//fWGujO0NGGzNO2cjKIotLS0cPHiRcrKyvQMICPQ3E5GTbqLdWPJssypU6cYGhpi165dtLS0GC5Cc7G4pJ9zSlEZSco4xQk3FYBNEPBIEwUCo4qKR1raBc7pdFJZWUllZSWqqjI2NkYwGCQQCNDa2ppRP6WoqOiyecpMJ9fCIhJKMDYUR5FV3Hl28kucSLbZRaoZ3Bf+6hq2vff9tL7+C8YGB0kkEjjzC7jqfR8kv2Tmuj9GoVl1JEnC6XTqAf+pVIp4PJ5h9Zjco84MGCHCzHAfGIUldhaIqqqcPXuWs2fPUl9fz5kzZwy/0bUMMjM07ZxMLBajqakJWZZpbGzk4sWLxN5NITUC7QdmlBl1MZadaDTKO++8gyiKenzOSnyik1FRAPuk120CxAB5mU9HyyIrKCigtraWVCqlBzq3trYSj8fx+Xy6y2uhgc5m+95yuUgOXhjnYssIiYiMIEyUECiqdLN6WxE2x8y/K7Ms3Ku2bKd8XT0jvT0MDA4SFyTK121YlrFoMXBaHKaiKLq7S8v60iw+NpvNNCLBitmZwPRix4zZWIlEguPHjzM+Ps7u3bspLCykpaVlRaWJL2afWu2g0tJSvedTLgKKwbiFaTpxoqoqiUQf8XgvoujE41mHKGbWh9HOtby8nM2bN+vjMjrgOVekj9EuCDgEgbii6pYdgLiiYhOYErOTy7HMh/T6KaqqEo1GdZdXV1dXhkvM7/dnZW43w0KukSthERtP0dM6CioUVU64A+WkwlB3BG+Rk/K66ds5aGMyyyJnd7oorV1LTLKTGp7aj2q50FquaBWGtfVFs/xor2niZ6nvOSP6WFkxOysUI4TD8PAwx44do7CwkMbGRj2wbSVVO15oGwpVVens7KSjo2NK7aBcBBSDcfFKk8WJoqQYGvpPYrHzaK2eR0Zeo7j4DtzuuowU+k2bNlFTUzNlfEaLnVxYBtMRBYFSh40LsSThlIJDFEipKikFKpwSjhyLncUgCAIejwePx8OqVatQFEUPdD5//jynT58mPz8/o0v2TIu1GUVqLhbCcDBOPJLCV37JtS7ZRRwukeGeyKxiZ6mzsZKRCOGBAEoyiSM/H29JOeKkRdasVgZNrGouL4fDobu8ZFkmkUgQi8UQRXFRKe7LgVmv+Xx55JFHOHXqFBUVFVee2FlogHL6Ql9fX8+aNWsybtaVXABwPiSTSU6cOEEoFNKtWYvd51xjBOPETnoRQEEQCIXeIha78O67E4ufqsoMDr5EefnHOHOmi6GhoRlT6FeCGwsmrl8ikdCfPgtsNla77QwmUsQVFYcgUOGWKLavrKc3URQpKiqiqKiIdevWkUgkCAaDDA0NcfLkyYyqucXFxVMCnc200OTMZaSqCEw9V0EUUObwWS6lGyvc10t/80lS8SgIAiDgKfJTsWMnNucloWbmhXfKNU5zeWnxPqlUalEp7tlixHcoy/KKtuwkEgn6+vro6+u78sROIpHIertEIsGJEycIh8PTLvSQuw7ludhvtsJkbGyMd955B4/HM2NaeS4sO0YWApzsFguHTzG1vTOASkvLQSKRylk7s+dK7Bi5wAiCQCqVIhQKAegTrNfrZb3HgayCKKBXSF7JOByOjC7ZWtXc/v5+2tracLlcutUnFxmZiyFXwsJT6MDmkIhHUjg9E1O9qqjEIzLFNbNX0l4qYZGKx+lvOYWcjOPIL5j4zcspxoODDHd2ULpp65KPKRcYleK+1Kzkaw7wF3/xF/r/m/4sjE49z1Y4jIyMcPjwYQRBoLGxcVqho+07F32scrHfbARUT08Pb7zxBpWVlVx77bUzxkXkwt1mpKDQC5OpKqCgqtOLXlVV8Xgkdu/ePWt/p5Vi2ZFlGbvdjtPp1M8nEomgqio2UbgshM5ktKq5a9asYefOndx0003U19cjCALt7e20tLQQDofp6upibGxs2b/HXB3fXWCndI2X2HiK0YEY4WCckb4Y+SVOSmpm71O3VJadSHCAVCyK3XMp2FyUbEh2B2N9vShp85SZ4ojSWci10lLc3W43eXl5uN1uRFEkkUgwPj7O+Pg4sViMVCo15f4IBAJ86lOfor6+Ho/HQ21tLXfddRcHDx6ccVzJZJKvfe1rbNiwAa/Xy86dO3nppZfmHGdLSwvvf//7cbvdVFdX88gjjyz772UhqKp6ZVl2sglQVlWVrq4u2tvbp3VbTSaXMTtG73c+AkrrVt7b28vVV1+tN9mbCbNmjaXvC7SAOzs2m49UamTK5wQBKio2TTupxhWFN0YjxFUVFwI+E//o0zuca+eimdYTiQTJZNL0zTqNwmazUVJSQklJCQDnz5/n4sWLhEIhzp07hyiKGYHOS31dciUsBEGgckMhnkIHI31RUgmF/GIn/ioPDvfsU/9SiR1VlicMrNO42lRVQVUUSKs3lq3YUWQFVQVxmirhZmG+Ke6SJNHd3c0tt9yCz+fjG9/4Btu3byeZTHLgwAE++clPcurUKX2/6aLky1/+Ms8//zzf+c532LRpEwcOHODDH/4whw4d4pprrpl2XKOjo9x///3ceuutHD16lNbWVu655x68Xi8PPfRQzq+LkQiCcGWJnfkKkvT4lPm2PViKVhRGMZeIiEajNDU1oaoqDQ0N8+r5kovsJCPdWJmWHSgs3M3Q0IHJn8JmK8DjWTdl+4PBMf60vYfR1MR4JBzcIyX5sklSdC3mj2bp2rFjB4qiEAqF9A7Zzc3N5OXlZTQxXYqKzrm6h0RRoKjSQ1Fldn2blsKKoqoqdrcXUZKQEwls74pMVVWR43G8pRWIae12sskMSiVkhrrDjAVjqIqKK89OcXUenkLjhWxsPEE0lcSb78aVt/gCfDOluKdSKT7xiU8A8POf/5yCggI9xX3r1q3ce++90+4L4LnnnuPzn/88H/jABwD4+Mc/zoEDB/jrv/5rfvjDH047jueee45EIsH3v/998vLy2LZtG62trTz++OPs27dvxc17phc7S11BeWRkhKamJvLz87Nqe3C5BCgPDg5mpFrPd3LJlWXHaDeWNkaPp554PMrIyBvYbEkA3O5aior2IgiZ59wVTfDHLd0ZdWhkBL4XlrlqMMRdpdO7NpcTzaozuTCj1npkMT3bLidEUcTn8+Hz+Vi7di2JRILh4WGGhoY4ffo0sixn1PZxu92GT/JmqWmTTq6zsWKjw4z1BUhGwgiSRHI8jJxIINoklGQSm9OFv25dxhjma9lRZIWe1mEioQSSTUQQBCIjceLjSao3+XHnG1MROJWQaX+nh9GBiP5aYamH9ddUzVrDKFu0FPexsTF+9rOf8cgjj1BQUDAlxd3r9WbcS+lzZzwen1Lw1u128/rrr8943DfeeIOdO3dmPOzecccdfP7zn6erq4u6ujrDznEpWBEznlHxEbMJh/RU4/Xr11NbW5vVj32lpZ5PHmt6kcTNmzezatWqrPZpdjfW5AlgYKCPjo6zFBevobi4Co+nDptt+qDNH/WNoKpTw5kF4Hu9QVOKHQ1BEEgkEhkVqT0ez4rOsFgss4kLh8NBeXk55eXlqKrK+Pg4wWCQwcFBOjo6cDgcuvApKioyRDSaUezkckyx0AjBzg4UOYXd6cJdVAKCgCrLSHYHeWWV+GrW4CosythuvmInPBwnOpbE7rIhvltOQbQJJKMphnvHDRM77e/0MDoYyXhtdDBC+zs9bLq+ZoatFnG89nZUVWXz5s04HI45U9zTv8Pbb7+db3/729x0002sW7eOgwcP8i//8i+zrlmBQIDi4uKM+6C8vFx/byWJHUVRVobYMYqZBEm622rXrl0UFRVNs/XC9r1YlsKyk0wmOX78OOFweMG9vXIVoGzEPifSPkcRxRDJ5DiBwFni8TeprlYQRYmxsYtEImcoLr4Vu90/Zfvz8QTTjUIFzsWyz+7LBbIs60GNoijqT2OSJOHxeEilUgiCgNPpvOK7jM8XQRDIy8sjLy+P1atXI8syIyMjBINBOjo6iEajU5qYLvQ8zXZ9cunGGh/oR0klcRX4AJAcYHM4SEYjFNdvwlUw/cPDfMVOPJICVF3owLvV6G0isXDSiFMgGk5kWHR0VBgdiBALJwxxaWXsepoigbOluGtejEgkwje/+U0+8YlPsHXrVgRBYN26ddxzzz08++yzsx5v8n1pRKHC5SCZTF5ZYme6AOXR0VGamprIy8tbVLfulRSgnP6Ur6WVa+e/0IXQrG4sWR4nFGoiGruAZDvB6eYLuFzjeD0gy14kqQJBEJHlMYaHD1Fa+lv6Dzke7yMSaeded4AdRQK/iJZyJFbMhE1nIpWx3j0RA5BSVUSWJ407lUoxODhINBrVxz4+Pg6gW3ImE5MVwimFlKrikETyJTGjqvLlzkIma0mSKC4upri4mPr6emKxmF7b58KFiZpNWqxPcXHxvAOdzWjZyZUbS1UUkpFxJEfmtRFtNlRFQY7HgOnFznwFmGQTJiyxk66roqg47MYIuHhk9oecWMR4saNlFDY3N3PXXXdN+5n0FPdYLKaXm/D7/fzwhz8kHo8zOjpKTU0NX/7yl2e1zpSVldHX15fxWn9/P3DJwrNScDqd5k89N5J0QaK5rd566y1qamrYuXPnorq75qrOTq4ClAG6u7t58803WbVqFTt37lzUE78Z3ViqqjA6+ivGx1uQZTuKXICcaiUe/y9GRg8RDP6CwaGXSST6EUUnqdQwyeQAALFYN8HhXxCKnKVIjLPdOcrHCzu4y3tR378CfLA4ny909PK+prN88Hgnf31+gGBy4XVcFCWBLIezEnnhcJhoNKqnlzudzlnbbYylFM5HUwQSKYaSCj2xFBeiSWKy8aUTzIhRcWAul4uqqiq2b9/OjTfeyFVXXYXH46Gnp4fDhw/z5ptv0tbWxtDQ0KxzgxnFTs7GJAhIdgfKpNhJVVFAANE28xw0XwGW53dhc0gk47L+UJdKTmR9FZa659x+Pjg9s68VrjneXwh+v5/bb7+dZ555Rn+YSWdkZGTKa5NT3IuKili1ahWRSISf/vSnvO9975sxxf26667j17/+dUZtugMHDlBVVUVtbe2sY+3t7eX06dO8/fbbNDU10d7ePqV3oqqqfOUrX6Gqqgq328173vOejGwymIg1evDBBykpKcHr9fJbv/VbdHd3z3GlpmdFiB2jfnSa2EkkEjQ1NXH27Fl27drF2rVrF32MXNXZyZWIAmhtbeWaa65h3bp1iz5/M7qxkskhYrFu4gkv7W0XkKQhnK4+BEFFEJzY7D5SyRFGRt9AlqOoqoKixFFVheHQCcKpOIOKh5DqAikfBZH3ewP4xTge4GMu+D8Do7wSDJNSJ0TEj/pG+Ex7L9EshYMsRwgGf053z99z8tx3eKf7n7gQap3XtpFIBFEUM75DLZZk8r0jqyr98RQpVaXAJpFvE8mXBCKywlAyN/eZGTF6IRdFkcLCQtauXcuuXbu48cYbqaurI5VKcebMGQ4dOkRTUxPnz59nfHw8Y2ExY92SXLmxBEHAU1KKqsikYlFUVUWRZWJjIezePJz5M7vQ091YiqIwEuhhJNA7IZTScLhslNcVYrOLJGMyiVgKVPCVeygsyy4rbSbceQ4KSz2akTftBCeClI226mjs378fWZZpaGjgpz/9KW1tbTQ3N/Pkk09y4403zrjdm2++yf/7f/9Pf8D/7d/+bQA+97nPAROi4vHHH+fWW2+lv7+fUCjEf/tv/w2Hw8G9997LyZMnefHFF3n00UfnlYk1NjZGWVkZmzdvZsOGDaiqSmtra8Z89Pd///c8/vjj7N+/n6NHj1JRUcFtt93G2NiY/plPf/rTvPjii/z4xz/ml7/8JeFwmA9+8IMLWhOvKDeWFpR55MgRvF4ve/bsWZQ1Z/K+V4JlJxKJ0NTUBMC11147r7T6+aCJHSOfCBfrxpLlKIODvQwMSqyuqaGn9x0AJCkfVU0hIGK3F5NIDhCNncPr2YjdXowsjxNOjjCuOnCLEoIAblEkKnrxEOZ79R5sAwo/GFcYSMhUOmy6+yqhqJwaj/Hz4TC/WTK/2CdVlRkY+HcCw2/TFncyrNhwKM20jJ4j3//fuL1iy6x9q6a73jNdt5isElMUvNKlhUwQBFySSDilkpzUJPRyZCnEhd1up6ysjLKyMlRVJRKJ6C6vs2fPYrfbdXeXFk9lJnKZjeXxl5CKx4kM9hMbG0EQRFz5+RTW1Gakmk83JlEU6Wk5zdEX/w+h/gAAhRWV7P5v/5OK+o36Z/OLXbgL7ERGEijvpp47PcY241x/TRVt7/QQSs/GKpnIxsoVdXV1HD16lK9//et89rOfpbe3l9LSUnbu3Mn+/fszPpsuWGOxGH/+53/O2bNnycvL4/3vfz8/+MEP9NpTMCFQOjs7GR8fJxAIoKoq3/nOd/irv/orPZZ137597Nu3b85xbtiQ2Zm+traWY8eOEYlEdA/CD3/4Q774xS/y3//7fwfgBz/4AeXl5Tz//PP8yZ/8CaOjo3zve9/jH//xH3nve98LwD/90z9RU1PDz372M+64446srt0VI3ZUVaWnpweAyspK3f9pFCshZmdgYIDjx49TUVFBKBQyTOhBZjsGI8XOQoVeKpWi+UwnY6Fx1q3bTH5+Mb2BCAIORBEUOYKqygiChKrKKHIMr3cTkuQhlBgjoYBdUPVaZ4IALkEFVaTS6WRMjHMmpeC0ZVYhdogT8QJnInF+c55jjcUuEAo3cyZVQr9qx28XkYQixEQnXSNHedNbx02FMz+Rut1uYrFYxpOvds9MCTB8979JRWVcUYjJCjZBwCUKl73IWS4EQcDr9eL1eqmpqUGWZUZHRxkaGtIXF7vdztmzZ/VA5+WuFJxL15ogihRW1+AtLiUZiyJKEg5vHsIc56woCuGBPt744XdJRMexuyZ+E8Hu8/zX957mA3/6ZxSWV+qft9klCgxyW02HzSGxafcqhvpHkLDj9jpyZtFJp7KykieeeIInnnhi1s+li/q9e/dy4sSJWT//la98ha985Sv6toFAAIfDwbPPPks4HMZut1NQUEAoFJqxk8BMaPORZnFOpVIMDAxw++23659xOp3s3buXw4cP8yd/8if8+te/JplMZnymqqqKbdu2cfjw4azETjweXxliZ7E/ulQqxcmTJxkeHgbI6NZtFGa27KiqSkdHB52dnWzZsoXq6mp6enpy1rjTqIl6oWInEonw9ttvY7e72LzlPSTi7SSTdiCflNyLy16K01GKqiaQ5RiiYKegcBcFBTvfPbCHUaGEUrWHlOoAQQRVxUGUMB5UWxmC0I0XlaFJVgJtgkm3nMxFIjnEaDLGkFyE3yZge/felKRCiuQ+jobCNBS49dcnk5+fTywW033i2hOdVmsnHbckICBwLpZCfrdRpHaFV7lsV4zgWU5LihYw6vdPZP61tbUxOjpKJBLh4sWLqKqa0cR0cn2UpWApigraXC5sWZybqqqcf/stEtEIrvxC/TuU7HbiYyFaD7/Gdf/tI7ka7oxjcnps5OfP3mtsuVhMdqAoirjdbtatW4csy4TDYUKhENFoNCuxo6oqFy5c0NtixGIxfa2cHOhcXl7OuXPnAHSxNTk7ury8nEAgMK9ja+vRL3/5y5UhdhZDKBSiqakJt9tNY2Mjhw4dWjEp4kbsN5FIcPz4cSKRCDfccAP5+fmG7HcyRncph4XF7GjWq6qqKjZu3IiqJgiHvUSjXQj4kaQxQMFm86GqKRSlH59vD2WldyIIE+eQJ4nEnNsYjYXxqeF3zSEqEdVFn307WxxOoqJIg03hvAphWcb77vkPpWQ8ksAtvtl7D6UjiW5SKqhqCkm49GQoqjEQSxBTKYZHRrELE+4Rl8uVUSdHkiTKysqIRCJ66rnb7dYnjYxjCQIJRSGhqDjebQKqArIKo6l3X7/MBY/ZYmS05qybN2/WMySHhoYIBAK0trbidrt14ePz+ZakRlKuiwouBEVRCPX1ThHxgiCAIDDce3HKNuPDQc4d+zXhYBCvr4g1V+0kr7hkyucuRxZ7n6c/uEqSRGFhYdYWHZhozxKNRtm0adOU96ZLbZ/rvsvG6qi1xTlx4sTlK3Y0NdnS0sLatWv1IOT5VFFeCGYsKjg6Oso777xDQUEBDQ0NGdlWRgcU50LsZBOzo6oqnZ2ddHR0sHXrVqqqNL+5i8LCXeTlbaG9PY/SEheq+jbR2AUEQaTQdwOlJe9Hki65iURBYHNBCYfkPTiSFykQI0QVOyGpiusKSnG+azW5WVIYKyzgleAYY3IKVYU8m8j/qi5mo3f+T6xudx157mqKop0k5Gqcoh2bMoqoJohI29ioJlEScRKCQDweJx6P66Xi06+VVhMm/bXJJBWVqAKFdnHCqqOCJIBdEBhXVEZTMqWO+U8L2hNfMplEkiTy8vKWpY5PtphtIdfGIwgCBQUFFBQU6AHOWkXnlpYWEokEhYWFFBcX4/f78Xq9hp+L9ptbblfaZBRFIa+4hOHzXVMqBauqSp4/U8QMdJ3l9R89S2RkhAn7pUjr4ddo+J+/j391rSFjMptwnsxi7g2t2vpiOH/+PKOjo2zcuDEjbEIT7IFAgMrKS67H/v5+3dpTUVGhVzRPt+709/fT2Ng4r+Nr5R+uuuqqlSF2sv3CUqkUp06dIhgMsnPnToqLi/X3zGqBMXK/qqrS3d3NmTNnWLduHXV1dVOuodFiR3vaMlrszGd/qVSKEydOMDo6OmNRREnyIIoFuFzrKCu7mUikjXiiHwGBePwCsjyG212HJHlQVZUyW4rfKLRxPl5Df8qO32Zjp9tBpdOun6+Eypdry/gtn0Jb8G3sxNletIG1RZeOr6opZDmKKDppjSq8Phohrihsz3NxQ4EXuyggSW7WV/wWXdGfMjh+AUVUSYheusXd+MQaVrtcOJ1OZBXCKZnxWBzRFsVXkD/ntZlpMrYJAs40C85CJu1EIkFvby+JRELffmRkhPLy8nn1U1suzLZAzfakarPZKC0tpbS0FFVViUajeqBzZ2dnhkvM7/cbEoen/ebMJggVRaH22hvoOXmMWHgMm8OBIsvIySR2p5P11+/RP6sqCm//20+JjAyTX1yC8O6D09jQIG//6wv8xsc/Zdi4zHadNBYbd6UoyoIfXDRjw/DwMBs3bpxSc0q7r1955RW9EWkikeAXv/gF3/zmN4GJBBq73c4rr7zC7/zO7wATKe0nT57ksccem3MMR48e5ciRI1RXV6+cmJ1s0IrkaW6r6S6y2QOJF7NfWZY5ffo0AwMDU4TeYvY7H3IhoOba3/j4OO+88w4Oh2POopBa25FUapREYhABEEU3oJBI9KMoCfLyNpNIDJBMjuBQU9RLEpsc+bhc1Yiifcq+QqFf4wj8gA2JQQAiEScXwruprr6PSKSN0Ng7JJMjHIsI/L9wDS1sQhUkJEGgsdDDV+sqcEsibncNt6z/I37R20xrNEwIP6vsRWwnSZXbQTAlcy6WJCwr2BQZjxxincPJKtfs5zsZmwA+m0hfIoVDuJSuHlFUnKJAoW1+LhJVVRkYGCAej+NwOPTrkUwm6e/vZ/Xq1aazDBiKqoIsT3TkXuRiN99FSRAEPB4PHo+HVatWoSiKHuh8/vx5Tp8+TX5+vu7yKigoWNB3YNYquYqiUL6unqvedydvvvAjEuNh/b2CklJ8acHJI4EeRgO9uAsK9MBnQRDwFBQyNjhA8OIFcCw+eNlswtlIFhN/ef78eYLBIOvXr0eSJJLJicrV6S7Y3//93+fLX/4y9fX11NfX8+ijj+LxeLj77rsBKCws5A/+4A946KGHdEvmZz7zGbZv365nZ83Gr371K7797W/j9/tRVfXyETvp1oy6uroZa8eYOZB4sfuNRCK88847SJJEY2PjrIGNy9FNfSH7m20yGRgY4NixY6xatYoNGzbM+cPUxheP96GqyYzWEIJgI5UaYXz8LKoaQ5K8iGIeipIilRomHhdxuVZnuBsUZZSLPS+QTA7jcq8BtErMr03EwaTCiKKNQcXD8VCAzeoF/PYE5xy7icgKh0bGeXFglLsrJky0HpuLW8u3cjMCcUXBlkwwFgoxLiu0RRMkFJUCm4gkK4RklSOhCO+1SRTNIlAmXz9BEKhx2wnLCqGUgigIKEyIoDUu+7zjdVKpFLFYDJvNlnFNbDYbyWSSaDSK15sZt2SmhWExC7nU24v9bAfiWAjVbie1eg3JtesmhM8CWOh1EUWRoqIi3cQfj8cJBoMEg0FOnDiBoigZgc5u9/wWdzOLHUEQaDvyyym1dYIXL/CLH/4dt3380xOfleV3RWTmnCCIwkQ9LQPXALNdJw0jLDsLFTsDAxPFWVtaWjJer62t1V3tf/iHf8jQ0BD3338/w8PDXH/99Rw4cECPKwX467/+a2w2G7/zO79DNBrl1ltv5dlnn51X3Nqdd97J9u3bdYvoihA7c31hmttqaGhoVmsGmMvdNB/ma4Hp7+/n+PHjVFdXs3Hjxnkv/EaSC7Ez3f7Sm5ZmxufMjmZ9kOUwguCY9J70rtUniM1WhCxHSCaDCIINSfKQSoVQlDiS5NL3JcttJBKDuN21+qRqsxWQSoUIBn+Or7ARl2sVZ0fGGaSEKilEhdJKQN0MUj4hWeZAcEwXOxpOUcApSsiCg4gk0RdLEJWViVgaVcWmQp7LxUVZpTuWpChv+h/+TA1082wi2/Od9MdThOWJgORSh0SBbf4T2+Ru6unH1N43K4sZm9TTg7PpbUilwO5AiMawN59GCIdJXH3Ngqw8RqV5O51OKisrqaysRFVVwuEwQ0ND9Pf309bWhsvlygh0nqmJ6XLF7KiKgpxMAALSu9ZCDW0eCJ7vZPB857Tbdv76LcZHgnh9fnwVVXiL/IwNDZDnL9Z/C9FQCHdBIUVVNQy9m527qDGb+D5fLIqiLDgYfteuXTO+p2WNCoKQke4+HS6XiyeffJInn3wy6zGsWrUqo6H1ihA7szE2NkZTUxNOp5M9e/bM2Y8mlwHKRhfVS9/vTKiqSltbG+fOnWPbtm0ZwV6zYcaKx9Ptb/JkosXnhEKhrJuWauOTJC+ynFluXVUVQEFVFcbHTxOJtKMoMSRbPm5XLS5XNaqamrSvKAJMeXqcsPCMY7f7AEiqE9ckJhRQpF7ErYSIS/koKvQnUpyPJahxTvWNawG/iVgQr5LClpwoqZ+yO0g5nNiTMmFl9sl2psnYJYmsXkRJe63/jtZRXbvnU6kUkiQtS7p0NizoN6qq2NvbICWj5qXFSyUS2Hp6SK1di1LoW8BujU/zFgSB/Px88vPzqa2tJZVKMTIywtDQEG1tbcRiMQoLC3Xxk5eXp1+T5YjZSYyHGQ8OIsdiIAg43G48xWV6arp2H4eHBmfeiaoSHhrE6/Mj2e3suP0DvPnCjxkbHESy296N7XGx/b0fwD7PvmXzwYyWHSOsc0YEKC83qqrqom3Fih1VVbl48SLNzc3U1tayfv36eX2xubTswMQNMtMT00L3q31hk2+8RCLBsWPHiMViGWnl82ElxOyIoqj7euFSfI7T6aShoSHrYEzNLeZ0lpFMDpFKhZAkL6oqI8thbDYf4XAzQ8GXSaXGESakDOOOM/iL3kN+/tX6vibutTIE0YYsjyNJEy6bifL3YRyOMhQlBuRR7XQgEgU1RgoHUVxcjCcYSirYBPjGuX6uznNzc2qc4MVufD4fxcXFFBYW4nK5cBcU0DY6jsMuoUoSss2OwkRmlW8Wa0wuJ2FBECguLqavr08XPJrQn81qYAYW+jQuxOOI4TDq5PvObkdIxBFHRxcsdnK9YNpsNkpKSvSKudFolKGhIYLBIOfOnUMURT3I2ePxTFujKVcko1HGAj2oiozN6UJFJTY2hpxKUVhdg2iz6/OKr7J6xv0Iokh+SZn+9+odO3HlFdDx1mFG+wPkl5azbtcNVNRvzOj3tBgsy4650TKwR0ZGVobYmfyjS6VSnD59msHBQa655pqMktdzkasA5VyJnZmK9Y2MjNDU1ERhYSENDQ1ZH3OlxOxo+9PcdDU1/z97fx4ex3me+cK/qq5e0Wg0GjtIgAABENwgbgBJ0JasTGwpdhIrmdienGRyHCfWN4pHXiTFlyPnyozPUSbyTBzFluVYST5NbI8zSjIn8TdHiRzLsmxZCy2JwkISAEGQBAgSe6Ox9d61fH80q9gNNIBGoxpoWL6vy5fFRvfbb1VXve9dz3M/z11HS0tLTk8cemTHai3D5WomGk1WYXHLNsJqreTGzb9ClpNkJZnaShCLTbO41EN5+b1YLE5jbrAHj+cE8/NnsVhcCIINWZ7HZqvA630X4cgwomij2VnMXrtKKDLJiLiPvpibkKrisYh0elxowHfHphkJzfE7dZUEg0H6+vpQFIXS0lLspT4kyckVRMpFCVQNf0Km0mZhd4aIkA4NiCPkrXeO2+1GFEUWFhaS1Q6SRElJSVr5+08TNIsFLCKCopK2xWkaIKBtonJlq6MDTqfTCPOrqsri4iKzs7PcvHnT8Ca6cuWKQbrz+YQfCy6iyAkcKb5YYrFEfGmReDiEw+M11oHKhr1UNbcyfW0oTbcjCALNp96FaxnZrNzbTOXe5rzNXf/uQoMZkR0zG8RuF/Rj+LM/+7OdYQSaiqWlJc6ePUskEuHMmTMbIjqQv8iO/iRk9tipJApudREdHeWtt95iz549HD16NCdytRM0Ozo5uXr1Kr29vRw6dCgrPdJa89MXAbu9muLiYxQXH6G4+Chu92Hi8SnkxBw2ayWiIN2agw2r1Uc8NkEiMZ82NxCo2/3/oab617FafQiCBa/3DHv2fIaqqn9Liec4shwkFrnKvZ4YLb47CDg7QYAmp5X3+dwUW0Sis35ciSgLVbtwVddw4MAB3vWud3H8+HE8Hg/B6SlsgxeJXx9mZGKSmaUlGu0S7/a4KF6lU/N0TOaGvZgxVylvLUS4FIzlxdXc5XJRU1NDQ0MDu3fvpri4uCAX/1TkTC6sVuSaWpATSc0OgKoihkOoRS6Uisq1P78GtvOciaKI1+ulqamJjo4Ojh07hiAIxONx+vr6eOWVV+jt7eXmzZuEw2HToxlKLIbFkr6GCYKAhmC4o6em1u79jw+za//h1DfTdPIMd/773zV1XoWKyclJPv3pT9PS0oLL5aKhoYH77ruPH/zgB8Z7lv9GfX19fPjDH6apqQlJkvjKV76Sceyvf/3rNDc3U1RUxK//+q9z9uzZdefz8ssvc+LECRwOB3v37uXpp5/e3AGaCP08/NM//dPOiOzoGBsbo7+/nz179tDc3JzTpmexWEwLYaZCD5eZTXb0RVBRFCOiNTs7y4kTJ4x287lgJ5AdTdMIBALMz89vWJ+TCcs1QKIoIYqpHUG1pDWEICKIdpLLrXDLCT1hiJNTx7JYXFRV/SqVlfehaUpaeXp5+fvxeE7cSpe5aLHXcDgc57+NzlBvt6IpMmPjU9isVhqqqphJKAQVlTLrSs3FHYkEgUCAG7MBAjeHEa/LjJWWEr1VkplaaTMbVxgMxYkJFkQlgQCMx2SiqkZbsR1LgZORQkZ8/36EUAjLrB+iEQBUl4vY0WOQY0R3OyI7a0GSJCwWCwcPHkTTNEKhELOzs0xNTnPh9WvIQRsOm4OqPSXsbavG7d1cCbfFZicWWiI1LmaIpG+RIP0JXRAEHMUePvDwoyxOTxEM+CmpqqGoNPe1cDPY6t9uZGSEu+66C6/Xyxe/+EXa2tpIJBK88MILfOpTn6Kvr894b+q8wuEwjY2NfOhDH+KRRx7JOPY//MM/8PDDD/PUU09x5swZ/uRP/oRf+7Vfo7+/n/r6+oyfGR4e5gMf+AD3338/3/72t3nttdf4xCc+QUVFBb/2a79m7sHnAP0cBIPBnUF2dFHq9PQ0R48epaKiIuex8iVQ1sfOh+jXYrEQCoVu+T1Z6ezs3LQANB/EzEyyEwwGGR0dBchJn5MJ6wmonc567PYa4vHZW5E6C6qqIMvzFLkOYLfXpo2VSpwEQVxZ5ioI2O1V2O23/V8qbBLFFpHJUBg14Mfj8VBaWspELIFHEvGtUkZutVqpqqqiqqrKqLQJBAJMTU0ZlgJlZWWUlZVx0+JE1jQcmoqChl0UkQSN+YTKXEKhfAMdkn9akfMGZbMTO3Uai9+PsLQINjtyVRVs4vosNN1HavpCEATcbjcuZxGRMSfO2AKKRSYejXHl3DRXL45Te4edytoyw8R0o+fWXuwhtrRAPBREcjhB00hEwlidTmxFt7Vwyx9uPZVVeCqrMg25pZifHCcyP4e3qobSmvw5ngM8+OCDCILA2bNn01o7HDp0iI997GPGv5dfUx0dHXR0dADw+c9/PuPYf/7nf87v/M7v8Lu/+7tomsbDDz9MV1cXX//613n88cczfubpp5+mvr6eL3/5ywAcOHCAc+fO8aUvfamgyM6BAwd2BtmB5I/3rne9qyA3eR2iKOaNSPX09FBXV5dVP5lsUMgCZV2fU1KSNPvbCNGR5RALC2fRNBWv9xSSdDtys17fHqu1lIryDzA59Y/I8iICIqoWx26rprrmIwjCbSKyWln3eiiVLOxLhPmXuSWqS0qR3EWMxRKEFZV7Sj24szAQTY367NmzB1mWja66/QMDBCrqkGw2JFUxKqEtgoCGSkQprI11O7BpciGKKJWVUJl72mr5fAopspNpPvNTEWZGghT7HFjtyftAVTVmx4JYEyLBYJAbN26AJlBkK8FT7KWiykdJWRHCOnoxq9OJu6qGcGAWORpJVmO5iykqq0CUrLe+q/D0I9HgEv/85J9y82Kv8dqeO47x/gd/H0cedGuBQIDvfe97PPbYYyt6WAF4vd60f2/kmorH43R1dfG5z30OuJ02fN/73sfrr7++6ufOnj2b5koOcO+99/LMM8+QSCS23TpGPwcPPvjgziA7VquVI0eOmPIElC+BMpgf2VFVlaGhIRRFoaWlhaamJtPGXl7pZNaYmzn+VHf2w4cPoygKExMTWX9+avr/x9Wrj6GqyfSCINhobHiE2trfuvXv9Uvjy8rei9XqY37hDRJxPw7HHkpL30VRUUva+3IhO4qi0NfXR8vsLL+1dz/dCVhQFDwWC79U5uHnS4tQc/hNJEmisrKSyspKNE3jzdkg8/E4cjCGoshMT09hsztQbQ4kCt+36p2GnUB2goEYqqIaRAdAFAWcRTbEmI22thbCizGGL04TmFhg5uoUA/FRisqs7N5XSkVVOSUlJatW99jdxdhcRSjxGAgCFpt9RZ+dQjpHAN996s8Y67+Q9troxV6++9SX+NU/+ILp33flyhU0TctoqLkcG72m/H4/iqJQeYvA6+tkdXU1L7zwwqqfm5yczOhcLssyfr8/61Yo+cYv/dIv7QyyYybyGdkxc+xYLEZvby/xeByHw5GT2+xaKDTNjizLnD9/nmAwaJTRj4+PZz3e0lIvQ0N/CCl1MpoW59rw4zidDZSW3pmVsaggiJSUtFNSsnpTrOT7NtZTKBqN0t3dDcCdt9KQ9ykqi4pCicWCw5I8d5tVkwmCQL3bSSQkklA1pEQch9NJUFZQFxcYuNzLdIqR5FZ5WBXSRrUTyMV2IlMUxSJlnp+qaFisIqqiMT0chISV+pZdiBaBWDiOf2KBxeko/sAAiUTCaKuQWuKuQxDFZBoryzllAzkWY3ywj5nrw4iihcq9zdS0rE8W1sPcxBjXz3eveF1TVa6f72ZuYtz0lNZWdLZO1YjqD3Trfd/yvxdiB+6fKruIbLETyM7c3Bw9PT34fD6OHz/OG2+8YToxKSTNTjAYNPzMUt3ZNzLexMTfASKw/JhExif+ltLSO3NOPWXCRsZaWFigq6uLsrIyDh06ZDzdOi0izpS0lVmLQ7XdQlS1ciUaJSFZsVvtVDoFWqpKsdT6CAQCzMzMGF11da2P1+vd8X01diIKjexkmk9JlRObSyI0H8NVkuxuHI8qqKpGRX0RkaUE4cUERaU2REvys3aXDV+lF9Ei0Hj0INFYlNnZWWZnZ7l69SpWq9VoalhaWrpmyiMXspOIRen6f/+JyauDgACaxo2LvdQdPsKBf3Pvhs9LKuanJtf5+4TpZKelpQVBEBgYGOC+++5b870bvabKy8uxWCxMTU0Bt893qgt5JlRXVzM5mX4upqenkSRpTSeDrYYgCDuH7Ji1URUy2dE0jevXrzM0NMS+ffuor6/PW5VXoUR2pqamuHDhAvX19cbNrGMjv3k0dpOVRAdAJRoZNcYz6zxmEyUCGB8fp6+vj+bmZhoaGjb8lJQLBEGg0WVDmQkRiMRoqfZRIomIggBWN263m/r6emRZZm5ujkAgwODgIPF43Hjy1r2UCmkTNhOFdlzbOZ94RCY4F0dVVBxFVlRlJbFwl9ppuMPH9fMB5iaTncMtkkh1UzEVDW7CC3E0VTOIjg6LJKDIGpoKRUVFFBUVUV9fj6IozM/PEwgEGB4epq+vL83EtLi4OG0Oy8mOqigExkaZmxgHoLSmFt+uesQUsn7j4nkmr1yiuLwCyWa/daxhbvadp7yxGdy5V3d6q6rX+bv56Rufz8c999zD17/+dT75yU+u0O3Mz88bup2N7pU2m43jx4/z4osv8iu/8itGQ8EXX3xxTWLV2dnJc889l/baCy+8QHt7+7brdSD9POwYsmMW8l2NletmKssyFy9eZG5ujvb2dsPcDwpbTJzrmJqmceXKFUZGRmhra6O6euXisZHxXK4WFhd7WEl4LLiKWo3xtiqyo2kaly9f5saNG5uuIMwVNgFccoxSa+ZojSRJVFRUUFFRgaZphMNhZmdn8fv9XLlyBbvdbhCf0tLSn5qoTyFWP20F2YmGElx508/YpXlUFWpbPdQ0eQiMh4mGZAQhqcPBEUPLsDPUtHjwVDiYn4qgKRpunx1PpQNRFLC7JKx2C/GIgt11+8OxsIzbZ8diXZYWs1iMawuSaXu9o/PNmzcBKC0tNVJeqWRHVRQun32FicF+w9Dz5sVealoPsq/zTuIRhemRRQZe6SYSVLC5QLBoWCwCNqeLYCDA7OgIvoN35HwuS2t2seeOY4xe7E1vbiiK1B8+kreqrKeeeoo777yTzs5OvvCFL9DW1oYsy7z44ov85V/+JRcvXrw9l5RrKh6P09/fb/z32NgYPT09uN1umpuTTRcfeughPvrRj3LixAkOHTrEX/zFXzA6OsoDDzxgjPPoo48yNjbGt771LQAeeOABnnrqKR5++GHuv/9+zp49yzPPPMOzzz6bl+PfKFLPwTuS7OSzGiuXsfU0jt1u58yZMyv8vXZCt+ONjJlIJDh//jyhUGhNm4uNzLG25jeYmvp/0DQB0vrbquyq/ShgrnfXWmRHlmV6e3uN49vOjsLZbuyCIKx48p6bm2N2dpbLly8bUR/9yXu53mKnodDmLggC4sI84twcyDKa243iK9tUSXsq4lGF154dJjARNqIvg69Pc+3tWRqP+SipTEbx5LjC5I0lcGc+P0VeG0XelXOyOSVKa5xMj4SQ4yoWq0AiomCxifhq179W7HY7tbW11NbWomkaS0tLzM7OMjExweDgIFarFUEQmJ2dJTE/y8RgHy5vKTZnUnMWD4eZuNRHcXkNS4FilISaXAY0jXhERk6oFJcliZlZeP+Dv88/f+W/crPvvPFa/eEjvP/B3zftO5ajsbGRt956i8cff5zPfvazTExMUFFRwfHjx3nqqaeM9y2/78fHx9PMOZ944gmeeOIJ7rrrLl566SUAPvKRjzA7O8sf//EfMzExQXNzM88//zx79uwxPjcxMWG0BNHn8/zzz/PQQw/xta99jdraWp588smCKDsPh8N0d3dTXFyMzWZ755EdSZJW9ZoyY+yNkp3Jycm0NE6mOeUjspOv1Nh6UbNgMEhXVxculytNn5MJG0ljuVzNHDzwdYau/BHxeDKHbLX6aNr7R3g8R4355Tuyo/dDWq4/2g5sZkO3WCyGl5KmaYaX0uzsLNeuXcNms2046lMoEZVCmYcOTdNwzfqxjoZAlhFEEW1qCsvMDImWfWgmmKqOXggQmAjjLJYQb+nEEjGF0Fyc4Fwcb1WSNEg2CxYrhBY2/h1ldW6sDomFqQiJmIKn0kFptSsjOVoLgiDg8XjweDw0NjaSSCS4evUqs7OzDA4OMtN/nsTsLDjdIMax2WzYXC5CcwFu9l/FXXYHoiRQUt3A0swIqpoA2Uo8IiOKCSySRFl9A5u9ChxuN+//zB8QmZtlyT+zJX12AGpqanjyySd58skn13xf6v2vm8Guh9/7vd/j937v94wo2/LKr2984xsrPvOe97yHrq6u7Ca/hbh27Rof//jHqa2t3XmaHTOQar9gNtnZCClRVZXBwUHGxsa444471hSB/bREdnR9jt4Be73fdKNzLC19Fx3t3ycUGkTTFNzuAwjC7Us83wJlv99Pb28vu3btMq0f0mZhxvEKgoDL5cLlclFXV2dEfQKBgOGgnar12elRn62GNRGnaGkRiorQiouTm7CqIs4vYJmaRN7TsOnvmLkeAjCIDugWN7A4HYXUPU0AQcuuEicVoijgrXJSUulA0zAliqLIKpoi4HIWES+O09bWxoXIEtdDi0QiEeYCAURRxOlyIkejSKEE7vLksZXuamVx+jqLUyNomkYsJOBw26lvO0pFYxPTMzObnh+At7qW8t2ZOwxvFzYrev9pMAH1+Xx89KMfxWKx7JwOymYileyY/dSdrR4oGo3S29uLLMt0dnZmbBCVip2u2clGn2PWHAXBgtt9cJW/5SeNlSosP3DgALt37zblOzaLfBGO1KgPYGh9AoGAEfVJrbIpRAf0QiJjjlgciyyjpVh+IIpoDjtiIAC7diMuLSEsLSIoKmqxG7WkBKzZR0wkq8DyUIZoEdCA1FOhaRqJqILdk7vruU6iNgNV0ViajRBejKMpKpGQiqDZQIOqhkb814Zw+0qRbFVEI1GWFucJh0IUVTpRZAUNFVGU2HPsXuYnhlicvomrxEFzx2FqWvYjm7QOFFolXSre6SagtbW1/MEf/IHx78JbhfIMQRDy1uk4m9RQIBCgp6eH8vLytDLkzY67UeSLQC2PJKTqczo7OzekXzEzErPa/HKFTpxUVaW/v5/p6ekVwvJCwFakbJZHfebn55mdneXKlStG1CcWixGNRgticyiEOaRCQ2PV2WgalqkpxIV5NEkCQcQyPY0QCqHU7oIsH9hq93sZvThPPKpgtSc9phRZxSKJuEpsLM3GsEgC8YiCzWXBVra9W8OSP8JSIJJMq9ktqEsaQsLKUiBKeX0jVU0tTF0dMrozS6rGwZOdlDUex389gqaoxOVk16riyhZKqlqp2e+hrPpWv7I8+CMWEjZ7jecj87EdSO0XtGPIjpmLU75EymuNq2kaIyMjXLlyhdbWVurq6rI+JovFYnq3461IjS0tLdHd3U1RUVFO+pX1IjuyHERVI4iiA4vFnVVZt9mRnTfffBNVVTlz5symrUzMxnZs6MurbMLhsBHxGR4eZmxsLE3rs11Rn0IiO2HJiiqAEImg6U0eVRUhFkUpr0RcWkQtKoJbppiaw464tIS2uIi6Ri8TOa5wo2+eSDBBWa2LhmM+RroDxMMygiggWgQajvpobi9nyR8lkVAprXURkuNEZXPXm41AjiuEF+NINguSLfkwKEqgKBBeiFHktdN6589RVreH2ZtJsWzZ7noqGpoQJQk1Mc/8VBhRtaBpGpqmoSAz0j/ByOAYRWVWSis2Zyqso9CIs1n4aUhjAWnHsGPIjpnIl2XEamRHNzJdWFigo6NjhYfJetiJaSxdeN3Q0JCVPmcjc1TVBKFQP7HYBKqaQBQlbLYq3O5DiKI9w0i3xzMr0hEKJTUQDoeDtra2gl0YtluMq0d9pqamqKmpwW63EwgEuHr1KpFIhJJb3ZzLysooKir6qdw41kNckoj4fDgX5hHm5xAEEU1VUUu8qB4Plrk5g+gAIIhokoQQCQGZyc7U8BIv/fchElEFbhUoFpfZKalyEg0msNpFGo6Use90BYIoULb7dip9ZCSAENq+30GRVVRFxZZiWKupGoIlmd5K2lbYqG7ZT3WGbsg1LV5Ka4oIBqIsBaIkYgqS1Q64iMcSyAsy1xfH8Ja7iUajSfHqLaf3nxaYodkphD45m0VqOu4dSXa2MrKjRzecTidnzpzJyb17JwmUFUXh8uXLjI6Oriu8Xg/6zbr8xg2HB4lERhBFF5LkQtPiRKOjgEBx8dFVb3Kz0mI6kQMKmugUGnEQRdEgNi0tLUaFl95YLrWjrs/ny1vUJ9M1oKkqsXPnSAxexlJZgeM970HcokidpmlEKypI1NQgzqeWnvsQgyFWiG0AVBXEzNddIqYkiU7s1lp06+NLszEEEXYf8BJZSuC/EaR8TxFlu9I1g/nUa2iahnrLjNYiZf4OiyQiWkQURUW6dYyqpiJoAoJFSBNZZ4IgCDiLk+vswkwEm1MyvkuyW4iHZbyePSj2oLG2hsNho4GrJElIkrTu/VOItgg6NrvO7XTNjr5npB7DjiE7OzGNpXfP3Ux0A/KrrzHzolZVlWAwSCKRMKW/jNFELCWkqihRotExRNGJxZIUdApCclOKx6dQlBCSlPl7N5vGShVaHzx40CA8ZsJsndJ2R3bWgtPpZPfu3ezevRtVVQ2tz7Vr1+jr66OkpMQgP273+mnKjSB1LGV+Hv+nPk1iYABEMZlC8ngo//KfY29rM+07V4O+MKslJUnhcerfnCqa1YYQCaM5nEk1cTyOgIbiztyfavTiXDKikwFL/hiiJOCpcLAwGWViaHEF2clXaiYRU4gsxW6RMAGb3YKzxIa0rOmlZLPgKLYSCkQBsFhEVBlERFwe26okaTliYTnZb0dIRoYs1qRWyWIViYVlJKeA1WrF4XAkU12KgqIoxONxotEooigaER+LxVKQpGYtbFazU6gPcetBv35/8pOfYLVaOXHiBLCDyI6ZyFcXZZ2UqKrKpUuXGB8f58iRI4aTbK7IR2RHv5DNIjtLS0sMDQ0BcPr0aVNCoJnIjqpG0TQZiyV9gRYEK4oSQVWjQGays5k0lp6KXFxc5PTp04Y+p5DJxE5anEVRxOfz4fP5jKhPIBBgdnaW69evp2mB1vNRWo6QEiSmRXCJbhyic8VvNv/F/0ri8uXkP27dZ1owyOxDD1PzL/+MYhOJqzFEwYJdcJh+XtfsxO1woFZWIM7MIC4tJl+UJBRfOdoqzTgjiwmEpBVUhu8CRdawSGBzWQjNJW0ehJQy8XyQHSWhEgxEkROKocOJhBIosoqnwrkiWlNSkXyQiS4liCdk0DQkNxSXZTYKzfR9M9cXiUdkiCRfEyWBIq89aWuxzNhUT2VJkoTdbkfTNGRZRpZlEolEUuB6i/hIkmRqSjwfeCdHdvT94q/+6q/413/9V55++mk++MEPvnPJTj4jO6miVTNcpfMV2QFMIVF6Wqeqqor5+XnTcr36HFNvXIvFhSjaUNUoFsttUqOqMUTRhsWy+vnONbITDofp6urCZrPR2dmJzWYzyHIhL3hQ+PNbDU6nk127drFr1y4j6pPqo+TxeAzys1rUJ6ZGuRB+iyl5HEVTkAQr9bYmRG4TFnVhgcgPf2iQHAOqirK4wPi57xM90URCiyNiocjipkKqwbaGNmyjWI9cqCVeVKcLMRIGTUOzO5KNBlf5jG+XKyPRAbBYRay2200FPRWONKKjz8fsjS4WSZCIJ60k9GNNOqPLxCMyDnd6el+0iJRWFyH7FBRZIxCbwF5szbp3z42BANFgushalTVCczGsDgueChcRoqt+XhCSUR99LdOjPrIsE4vFjJRXIeOd3mdnbGyMcDjMo48+yszMzM4hO2Y+aeRLoBwMBonFYpSXl3Pw4EHTLpZ8aXZgc2Qn1f/pyJEjSJLE3NycWVO8vSGlzFEUbTgcdYRCl4EggmBH0+KoahSnc++6ZGejm38gEKC7u5uamhr2799vnLdUPVGhYidFdtZCatSnubmZaDRqaH30qE+q1sdqtaJpGt2hs0wmxrAJNuyCg4QW52qsnxJHJfVq0g9IWVhYSXRuIVLnJSLMUkQTRWIxCgoL8jyqprLL1oAomEMIsoqk2GyoWer9apo9+Ha7mBsPoy07tPL6IjQgshBH06C6aWVVUj42OiWuIlrSe/ck+/EkS+BXQ7IiCxBuRxoUWWZhaoKlmWk0TaW4vBJPZTXWWzY7iZjMkj+ScTxV0XAW2yiucBCZyb5NtJ7KstlsRspLr5ANBoPG3wtB6GyGlmgnR3Z0jI2N8V//63/F7/fzuc99jp19NDnC7MiOpmlcu3aNgYEBBEEwXbSaj8iOsdDkOG48Huftt99menqa06dPU1lZabroWZ/j8jFdrhaKivYjCBKqGkEQxFuvHVhzvI2GnkdHR3n77bfZt28fBw8eTLv5MxGxQkQhk7Fc4XA42LVrF21tbdx5550cOnQIm83G9evXefXVVzl37hx9oxeYio9jF+3YRDsWwYJDdGJBYt4xg0IyMidVVyNk0JZpAgTrS5Aqq3GITgRBRBKsFFmKCalLRNTw5g9EUSCRQDPZCFQQBd778Vbq23xG8MfqsFDb6sHpsbI4E0UQk2XnlQ0Zjj0PaSxREtDU9GtR0zTQtHUFx3DbLFVVFMYv9XHzYi+LMzPM3pxi4JU3ufCDnzBzfY54RCa+il5Jh9vnWOHOvhHoKS+bzWZ4ykmSZAidg8EgkUiERCKRl/VhcnKST3/607S0tOByuWhoaOC+++7jBz/4waqf6evr48Mf/jBNTU1IksRXvvKVFe/58Y9/zH333UddXR1tbW08//zzWc3n5Zdf5sSJEzgcDvbu3cvTTz+d87GZAf3aDQaDlJeX84d/+If84R/+4c6J7JgJMzU7iUSCCxcusLS0xLFjx3j77bdNXyzymXbL5WZcWlqiq6uL4uJiOjs7jaqZfFR4ZSI7gmChqGgfTmcDqhpFFO1rlpyvNVYm6JqriYkJTpw4gc/nyzgWFDaZ2MmRHU3TCCgzLCrzFInJ1FGm4xFFkdLSUqOZo+6ePRwcImqLkEjIWK0yVknCarUiCRIxIUbCkmwqJ9hseD722yx89an077dKCPubcezak/KihjYxRWxmmKX5a9j3tyPV1W384BIJpLExLP4Z0FQaFhewBpdgmTh5M3AUSbzn3zcRj+whFpaT/lSCQHA2hiKruEpsae7kqcjHU73NaSUaShCPylhvaXYSMQWLVcTmWH8b0ucUDPiZGx/DVeojEtTQtDj2IhfB2SmmR26SiO3GW722dMBRZG5JtSiKRpWtXvQhyzLxeNyYt1lC55GREe666y68Xi9f/OIXaWtrI5FI8MILL/CpT32Kvr6+jJGdcDhMY2MjH/rQh3jkkUcyjh0Khbjjjjv47d/+bT784Q9ndQ0MDw/zgQ98gPvvv59vf/vbvPbaa3ziE5+goqJi281Ao9Go4U7w0EMP7RyyYzZ5iJvQQXN50zx9joqimFo2m480FuRGTiYmJrh48SKNjY00NTWl/S75KmdfjVCIog1RzL6UP5vITjwep6enh0QiwZkzZ3A6Mwsi9ahToZOdQp7faoipUX689K/MyJPGax7RS5vtFLKsYhEtVDgqKLKutFnR3bOdso3A0jiCTUSTIRqLEQqHEawagiaiRW9HMNy/9VsgiCx+4xtoi4tgsVD0vnvh1z9CmDh2HKCqRF58kXDfReJOgWjXFLOJf6ToQx+i6Ffuy359UlWsV69gmZlGszvAYsGTiOMeGUn6YnlKEJaWku/x+9FsNuT6euT6PclKsQ3C5pSwOW+vRZ6K9cvp8xHZsdotuEsdhBfjRkm8ZBNxldixWLOL7IiiSHhhHk1TQZOIhcNYrBZEi4Acs6IklpDjCtFggtIaF3MTK6NvLq8dZ7HNlPVfP0+RhXmiS4s4PB6cHq9BalKFzoqiGB3EU8vbN0oqH3zwQQRB4OzZs2k2Q4cOHeJjH/vYqp/r6Oigo6MDgM9//vMZ3/P+97+f97///ca/s7kGnn76aerr6/nyl78MwIEDBzh37hxf+tKXtp3sJBIJSm49QMiyvHPIjpkwI1IyNjZGf39/2qavb/Rmk518pLH0cbMlJ6qqMjQ0ZOhzMlWYbYe56Eaw3uavR6w8Hg/Hjx9f9zfcqWSi0HE2+BJ+ecr4t6qpDMwOci5ynn22wyCAx+bhaPlRdrsz+5B5LWWUSZVMyxPY7Xbs9iLiapyYEsU5W8zMpJ9Xp1+9rfX5dx+h9v/4dZSZGUSPB7GoCJuyQCR+g5ASRLg0QujSeRIVbtwL4HSXo80GCP7D32Nr3YftYGY/tuUQFxcQA7OoxR64dX0FJSuliQSWyUkUTcPx6isIkYhRBm+ZmcEyO0vs+IlVRclmIl+l53aXFatDQkkkS88lq7hCHL0ajGjTrb47ckIFFUTb7QirRZKwWC1EQwlqWkrRgPkUwlNc5mD3wZVR2lwhx6IM//glglPjxmsltbtpec/7kG7ph7IROqdWea113gOBAN/73vd47LHHMvop6s1qN/v76WtaNkTs7Nmz3HPPPWmv3XvvvTzzzDMkEoltaUyoH/vc3JxRNStJ0s4iO2ZtLpshO6qqMjAwwOTkJEePHqWioiJtfpvRwayGfEV2sj0P8Xic3t5eotHomsaleuTEzMXSTIuHtYjT1NQU58+fzxixWmtuhU52CmV+2V4PIWWJ8cRo2mtz4UWmg35cViclrmKKLSXMRGbo8fdQai/NGOERBIFjRZ30ht7EL08SJ44kWmm2H0CcduLe46a0tJTZ2Vlu3LhBf38/7mI3YpVKLBZCVEUqrFX4pHLCapC565dQgRK/SslEFBEBzedDuXmT6BtvZk12hHAEQdWSPle3oGkams2ajOjMziZtI1KrrRIJpNHrJBobUX2r20OYhXyKU0VRQLRvfNvRK8ScpT4sVivxSBCwgAaJeBQBAZen7FY/HQsWSaTuQBnVTV7iYRmrw5JVumwjuPbqDwlOT6S9tjAxxtDL3+fAPb+U8TOZhM56yiu1t08mofOVK1fQNI39+1d2jTYT+p6QzTUwOTm5onFsVVUVsizj9/upqanJyxzXgr7WfOQjH0n7/h1FdsxCrtVYkUiEnp4eNE3LmOLQOzbuhAaA+rjrEYnFxUW6u7vxeDxp+pzVxgNzqznMNu9cPpYuLr927dqGHNlXG6+QsBM1O2E1tOK1ufACFsGCTbIS1SKUCKVUOCu4EbzBTGQmI9kBcIouTrnfw5K6QEyNUCQW47K46aMPQRDwer14vV6ampqIRiOcW3ydKXUMJaIghGFcGsUjeukovgt77xzKoB+bL/3hBgHU0Mo5rwqrBGi3OiCnCN4VBaxWpJs3wGJJj+BIEsRiWKZn0smOomCZnERIxFEqKtFWeQjZKArR70lf+1zeUiobm5m6coXIYoCQomFz2impqcPuLkWOqxSV3F6XrTaLoREyE5GFeRYnxlb+QdNYGL9JZHEep8e75hipvX0geYw6+QmHkxGpVOKTbZWVGVYR2XyPjuXvK5TO0t/85jex229rOd+RZCcXgbLf76e3t5fq6moOHDiwKunQVflmwuwGgDrWIzt6B+i9e/eyd+/edS/efJEdM9NYqWMpisKFCxeYn5/n1KlTeDwbMwfMF9kxc7MpZDKWCcWWEgQEtBSLBEVVsNy6ttxispGeKIgICCja2g8WgiDgsXjB4l3xeiqWLAss2QJ4BS+SkOyjFItHmVfmeGXoJZqsbtwLSyTcHqw2GyCgJRIgiNhamrM+PsXrxVJUlDT3LC4GQcSqyAiqhlJZiTQyvLoDekrKxzI1iePVVxBjMSDpCJFo2UfsRHtO2p5UFCrZ0SPnFQ17cfvKmBufYXEmjMVWhL3Ig6JoFJU6KCrNv81HVG/wuNrfFxfXJTvLIYoioiimpbz0pobRaJTa2loEQaCvr48PfvCDq/5GZjQUhOzISnV1NZOTk2mvTU9PI0mSYQa8XUglOrDDyM52pLE0TePq1asMDw9z8OBBdu3ateb78xHZuW2VYL4WKLPRpsrly5e5efPmilTdeuPpnzcLZqex9OsnEonQ3d2NxWKhs7NzxY2R7dwKmUwU2oaVDRyik732Vq7GLhmvFTuKmFr0U2vZTZElSXbCchiraMVj83AzPsKVaL9RubXXsZ8GW8uGNoOAPIOCglVICt6tkoRVciOq4NjjwvtLv0hsYADl+igRhwOLKCIlEtj27cPxrndlf4BWG/LeZqRrVxGXgqCpWDSI19QiVlah7NqNNHztduRH0xASCbBYkKuTIXkhEsH5ox8mS9dvQQCsQ5dRi4pIHDyU/XwyoBB7rKTOSRAEXCVeXCVeqptVoqEEmqphtVuwudb3tDIDjuK1H4wcG3xwygQ95QXJa9bhcPDe976Xp59+mt/5nd/B4/GkVXnNz88buh0zIjvZoLOzk+eeey7ttRdeeIH29vaCMxLdUWTHLGxEq3LhwgVCoVDWT/75KBNPrfIyE5nmqutzYrHYmvqcteZpJtkxO40FSaFfT08PlZWVK/rnbHS8n/XZyR7ZzqW96E4ERK7GBtDQ8Lm8WBMu3EoZs9FZZFUmrsbZV7KPRWGW88E3UVCSPXSUAF2hs4SVEIdcx1b9juWbgSAIoK2MamhoSKJE7R13ID/+JwS/8x3Cb76FrKoste5j+sgRnP39Rjdnj8ez7vWklpQQb7sDcXERFIXBSA/H6+txiCLxAwcRZ/3Jv2kkWYzFQnz/QbRb6480MgyKkjECZBu8tGmyU6iRnUzn1WIVKfKa1806WzhLvBRX72Jpajzdl0MQKKnZteGoznrQhc5/8Rd/wZ133sn73vc+/uiP/oj9+/cTj8f50Y9+xH//7/+d3t7ejPdZPB6nv7/f+O+xsTF6enpwu900Nycjk8FgkCtXrhgptOHhYXp6evD5fNTX1wPw6KOPMjY2xre+9S0AHnjgAZ566ikefvhh7r//fs6ePcszzzzDs88+a+rxm4F3JNnJRrOzsLBgXAydnZ1Zs9R8kZ2tcD5fXFykq6uLkpISjh07tuEo0mpNAM2c42bHAjh37hytra3U19dvalH/WWQnP7AIFk667+KI6yRBdRGXWETCpzC8OMxEaIJiazF7ivew272LHyz9v6ioOMXbvVXiaowrsX72OlrTXteR6TerkKq5JgwS06LYBQdxLUZUjRLXYpRL1UTUMM7du/F+8pOUKAqISVPJpnjc8PC6cOECmqYZ3Z7LyspWjxhKEqrPh6qqRFN6r2gOB4mmZqxXhhAjETSbnURTE4l9rcZHxVAoqelZdhwCQCSSfH2T1TiFHNkpFDS86z2MvPYjliZTqrFqdtHynvfl7TsbGxt56623ePzxx3n00UeZmJigoqKCY8eO8ZWvfMXo7QPJnlN6efv4+Djt7e3GOE888QRPPPEEd911Fy+99BKQXBff+973Gu/R+/F89KMf5Rvf+AaQbD0yOnq7gKCxsZHnn3+ehx56iK997WvU1tby5JNPbnvZeSbsKLJj1uK9HiG5efMmAwMDWWtVNjJ2rsiX8Fm/MXR9TlNTE42NjTmf63x0UTZjPL10HuDo0aObNmcFc6NO+UKhz28t2EUHdjGpv3Da4Ej5EY6UHzH+PifPElUjRupJh1WwEtNizMl+nLb6jGMvv769ljIa7fu4Fhs0UloCAk6xCFVTGYleptHRmuymnKJHs9lsVFdXU11djaZpLC0tMTs7y/j4OJcuXcLtdhs2FiUlJatu2Pp8rENDSNdH0CQJxedDiMWQbt5AdRej3EqhqyUlGV0+NbilA9rcOqnrYwoJhUjALFYbTXffgxaPEl283Wcn36ipqeHJJ5/kySefzPj3aDSKqqqoqkokEkHTNKqqqgiHw2v29rn77ruRZZm5uTmmp6c5mKHCUCc9qXjPe95DV1fXpo5pK7CjyI5Z0AnJ8nCtoij09/czMzPD8ePHcxJYFVq347WgE6iBgQHGxsY2pM9Za8xCS2MlEgl6enqIRpPGf3pee7P4WWRneyEJSX2GhgrcJiDqrfyPJGS/vAmCwD7HYeyig6FIH5Ig4baU4LF4ERFZUOcIJGaotWcmT/oYHo8Hj8dDY2MjiUTC8PC6ePEiqqoaER896pNauSKEw0gTY2h2W7L0HNDsdsSlJaTREZTqarBYSDQ0YDvfC/E4Qsr1JwDxQ4c3dA4zodDSWHo7i0IjO5D83Rwe75aQnGyhVwXrPWZ0obPe20cUxTQfr+W/taIo2+7vlQ8U3tWzBUgV/OoIh8O88cYbBINBzpw5k7OSfCdFdiAZxZqdneXMmTObJjqQH7KzmfGCwSBnz55FFEVOnToFmBftyAfZ0RclRVFMOY+FTMY2C7foodRSQUJLoN5yvNQ0jbgWo0h0UyZVZfzcaudEEJKRnFJrOXX2vZRKZViE5GZgxcaimr1xJIDVaqW6upqDBw/y7ne/m2PHjuF2u5mYmOD111/njTfe4OrVq8acxGAQ4nG0Zakv1eFAjEQQbpF1rDYi730fagpp1ySJ6LHjyI17NzTHTCg0srPRUuitQqHeW8t/P72bs8vlwu12G6nVaDRKMBgkHA4Tj8eNKNBmUoZLS0sMDQ3R29vLuXPnVhhDJxIJbt68aRS//MIv/IIRcddx9913G5II/X+//uu/ntN8UvGOjOzoWhS9uml6epoLFy6scLbOBfkiJWZHdhYWFpiamsJut3P69GnTqrwKiezMzMzQ29tLfX09LS0txuuFSHb0BmN6JCv1GtJLUjd6XRZ65GmzEASB40WdvL70IkE1iKAlBcUOwUl70buxCKs/na62cYqIGYXKKgrWDUSKMn3f8qhPIBBgZmYGSHai3eVwsC8hI8biWBy3CY+gKGiiBc16+/vVEi/h9/8iwuICQjyRJD4m3cOFpo/R7/9CmpOOQiNgsDZZzdTbR3/AunLlCpA02hUEIacOyKqq4nK5KC8vN4h86rz0xogVFRV85zvf4ctf/jLvfe976e/vTyuGuf/++/m//+//2/j3arY9G8GOIjtmduUVBAFZlhkdHWVkZIRDhw5RW1u76bF3QmRHt7rweDy43e4tKWfPFbls2JqmMTIywpUrV1b8rmYKqM0iE3p+XVVVpFuGlXqDMVVVDX8d/TvFW+LYQlz8zUAgGuC/X/rvvHjjRWRN5kz1GT5+4OPUF69MIdlx4gpXcCPox2mzc6ziKE3O/TjE1RfHtX6zYksJdtFBSA1SJLoRBIG4GkNFo1QqN+X4IBn1qaqqorS0lOnpaY4cOcL83BwL/hkc01NE7Q5sTgcOiwVHPIFcXw+2lWJnzVOC2XS2UCM7P63Xez6Q7e+nm5jabDYOHz7M0tISfr+fcDhMb28vLpcLj8dDSUkJRUVF6/4GJSUlhh/VcsRiMUKhEM3NzUxMTNDY2Mhf/MVfUFlZybPPPsvHP/5x470ul2tDDV6zwY4iO2ZB3yguXLhAPB7n9OnTFBcXmzL2dls7rAVVVRkcHGR8fJxjx44xNzdn6FjMwnZHdhRFoa+vj9nZWU6ePLnixjMz2rHZsXQtQmp7dn2RSo3kpJIhnQTpWCvqU0gbVrYIJUL8h5f/A5PhSaNh4A/HfshPpn7C3/ybv2FXUVKkm1AT9Mz08Jf9f8l0ZDoZkRHg7Og5/uD4H1DnXtuNfLVz4xCd7LY1cDN+nQV1DrSkNqhKqsVrSU9ta9EoajiMWFyMkGNPEf368Xg8eL1ehPJypAvncc7NIYfDxGSZKauNmVgM79gYPp/PlKfc9eZUSMSikNNYhTYnyD1yLYoiJSUlLC0t4XA4qKmpYXFxkcXFRa5du0ZFRcWmAgKZfkfdOuPVV19NIzt/+7d/y7e//W2qqqp4//vfz3/+z/9503v0O5LszM/PGymDM2fOmO5QHrvV1dRMbJZExWIxenp6kGWZzs5OXC4Xi4uLBW3cudHxotEo3d3dQLLZlS7QS4XZkZ1cx9Jz46kLwKqplWXEJ/Wza0V9dmIa67mR5xgPjad3UNYUInKEbw9+m88d/xwzkRleGX+F/3X1fzEVmcIluXBanTgtTkaDozx14SkeP/04opDbhl0qlVMkFhNUF1G1ZFm761aUB0CLxwm/8H2ir76KGg5jKfXivPtuHO95D8IGScLy1vpacTGJU6exzM5iicewO104rVaKAgGmpqa4fPkyTqfTEDl7vV7TiUmhVWPp5KuQ5lTo2My5UhQFm82G1Wo1rjP9wWwzcDgc2Gw2pqamUFWVeDzOl7/8ZSYnJ5mYuO0x9pu/+Zs0NjZSXV3NxYsXefTRR+nt7eX73//+pr5/R5GdzV7smqZx48YNBgcHsVqtNDY2mkp0oDDTWAsLC3R3d+P1ejlx4oRxzIXuUg7ZE4qFhQW6urooKyvj0KFDq1YT5NtrKxvo0Rx9U9nIZqW/N9VCRK8sXB710V/fSTg3cy6N6OhQNIU3pt4goSZ4deJVLi9cZiG+QLG1GItoISyHkQSJElsJVxevcm3xGs0lmW0csjknNtGOT8ws2A/+03eIvPACQpELweVCnplh6dln0WQF1/vem/EzqyGjj5DFgpLSGqEYKPZ4aGhoQJZlo6/PwMAAiUSC0tJSY1MyI+pTaBGLQtMQ6Si086TDDLuI5evnWg9j2UIURZqamrh27RpjY2N88IMfpKWlhfe///1p77v//vuN/z58+DAtLS20t7fT1dXF8ePHc/7+HUV2NgM9veH3+zlx4gSXLl0q2HTTauPmMl9dn9Pc3ExDQ0PaBbsTyE425ETvEZTpGJfDzGhHLsQpleiY8bSaKeqjjz8/P5/UnMTjxncVutbHJbkQBdGorkr7m9XFZHiSqcgUXpsXDQ1RELEIFlRBJSJHKLGVEFJDhBJrm3Pmet6VmRmiZ88ieEuw+HwAiMXFyBOTRH74Eo47342YIaIIoMkyieFhUFWse/Yg3HrfRuYiSRKVlZVUVlaiaRqhUIjZ2Vmmp6cZGhoyoj4+nw+v15tTCXEhprEKkVQUMjZrF5Gv37+oqIiWlhZEUeSVV16htraWU6dOpTU8XI7jx49jtVoZGhr6GdlZD6FQiJ6eHiRJ4syZMzgcjrySkkKI7KiqyqVLl5iYmODYsWOUl68UV+a7UaFZ4602R03TuHz5Mjdu3Mi6R5DZxqIbITtmE53l0BcoURS5fPkyExMTHDp0yCBlqSmzQhU5v2/3+3jx5osrXhcQeH/9+4krcRRVoaaoBofFQUyJIYkSIiIaGkuJJYqsRewp3rPqd2yG7MqTk2ihIJa6dE2Q6C1BnZtH9c8i7l7pnxfv62Pp2b9DGU/aC4gV5bj/7b9Fu+OOnK8DQRBwu9243W727NljNISbnZ3l0qVLaVEfn8+Hy7Wym3QmFBq5KOTITiHCDNfzfJ9vURTx+XwMDQ1x7tw5HnvssVXf29fXRyKRoKamZlPfuaPITi4/4NTUFBcuXGDXrl20trampQF2EtnZSGQnkz5ns2Nmi62qxpJlmd7eXkKhEKdPn8btdm9qPDPnthx6vlvX2eRTfyDLMhcuXCAcDnPy5Enjt18e9ckkctb/ezvx7pp388sNv8xzI88ZpeOKpnC8/DgfavoQwUQQp+QkrsQ5Vn6Ms1NnWYovGZ93Sk5+cc8v4rV78zI/sbgYwWZHi0YRUkpltUgEwW5HcK/0kpMnJ1n8q79GmZvDUlkJgoAy42fpG9/E9sADWV8LWiyGfPMmit8PkhVpVy2Wqirj85IkUVFRQUVFhRH10cvbh4aGcDgcaVqfTFGfjGm1bUahkh0orPNkFjKlsbKFoihpmtV4PE44HDZ6/QQCAUNn+IMf/ID/+B//I7/yK7/CPffcA8DVq1f527/9Wz7wgQ9QXl5Of38/jzzyCMeOHeNdGzHczYDCvIJMgF55dP78eQ4fPsyBAwfSbpidRnayjcIsLCxw9uxZHA4Hp0+fXvNpbqeksZaPFwqFOHv2LJqm0dnZmTXRga0vPU/V0uRbaBmNRjl37hyqqqYRHcDommqz2XA4HNjtdqN1vL74yLJMIpEwraFhLhAEgT849gd89c6vcl/jfXxgzwd4/NTj/Pm7/xy7xU6Zo4xWbyuz0Vl2F+3mZOVJXNZk6qvOXcf9B+/n3zX/uzW/YzNPvlJ9PdaWFpTJSVS9CVswiDo3h/34MSwZunPH3nwLxe/HUleH4HAg2O1YamtRg0ESb/wkq+9Vo1Eir75K5EcvE790iXhvD+EXXyR+y9xxOfSoT319PceOHePOO++kubnZiPi+8sor9PT0cOPGDcP4UT83sP2kNxWFSna2K7IzOTnJpz/9aVpaWnC5XDQ0NHDffffxgx/8wJjX8uu7r6+PD3/4wzQ1NSFJEl/5yldWjPvFL36R06dP09HRQWtrK7/yK7/C4ODguvN5+eWXOXHiBA6Hg+bmZh577DHDdPTGjRv09/czPp70D9ObCo6NjfFf/st/4bd+67fSTENtNhs/+MEPuPfee2ltbeVTn/oU99xzDy+++OKmuzrvqMhOtojFYmnO3Zk2w+0mJRtFNlVeuqdXNtoV2Jlkx+/309vba0TqNrppbaVAWY+kbMUGsri4SHd3N+Xl5SuIfSaYUdoOyVLxVyZeIRAL0ORpor2yfc1mfpA8L4FYAACf3bfiNxQEgRMVJzhRcSLj509VncJj8zA4P0iLpYXTVafZ591Ho6cx5wqsbCGIIsX//jfRviEjX72KGo8hOJw4Ok5S9Ku/mvEzin8Glgk8BUEAmw1lcgrhwIF1vzdx9Sry8HCSMN0qc1fm5olfuIBUU2Poh1bD8qhPOBxmdnYWv9/PlStXjKiP3qqhkCIWhaYhSsVWn6eRkRHuuusuvF4vX/ziF2lrayORSPDCCy/wqU99ir6+voyfC4fDNDY28qEPfcgw+FyOH//4x/ze7/0eJSUl1NTU8Cd/8ifcc889Kxr+pWJ4eJgPfOAD3H///Xz729/mtdde4xOf+ATt7e0ZzUCrqqooKSnBZrPx0ksvraiYraur4+WXX97gWckOO4rsZHNhzc3N0dPTQ2lpKcePH1+12spisRglu2Yin312Vhs3VZ+zEU+vfBC+fKWxNE3j+vXrDA0NcfDgQXbtWqmL2Mh4Zs4tE/Ktz0nF9PQ0Fy9eZO/evezZsycnAphKfICsGhqenz3PH73xRyzEF5LfqUGrt5Uvdn5x1TTS5fnLfHPwmwzNJ1vEt5S08H/u/z9p9bZmfH8mSKJEW1kbB30HUVQFm8W2/oeWYTO/h6WiAu/DD5G4chV1fh5LRTnSGua5lqqq5DWsqkZpuqZpEIshVFcjLS0hT04iFhcjrrKpyNdHEYrcaf18LKVe5OERlBn/umQnFYIgUFRURFFREfX19ciyzPz8PLOzs0bX24sXL1JeXm5ofbaT/BSahmg5ZH8EeTaKVOZAKs9vD6QHH3wQQRA4e/ZsGgE5dOgQH/vYx1ZNQ3Z0dNDR0QHA5z//+YxjP//88wCcP3+effv28Td/8zdUVlby9ttvc9ddd2X8zNNPP019fT1f/vKXAThw4ADnzp3jS1/6UsE5n+8osrMWNE1jdHSUy5cv09LSsu6iL0nST0UaS9fnKIrCmTNnNlR6ulMiO3ol3czMDB0dHZsy8jRboJxprFSCkE+ioxPAa9eucfjwYdOc3FP/f7WoT0yJ8Z/f/M8sxBewWWyIgoisygzOD/Lk+Sf5Tx3/KW1cQRCYjk7z5/1/zmx0Frc1GW09P3ueP3n7T3j89OPUFm2sYZlFsORcbbRZCBYLttZ9Wb3XcfIkkZdeQrkxilheAaKI6vcnNT92O0XnzxOZm0coKsK6rwXbgQMZ+vXkL2UiSRLl5eWUl5cTi8V47bXX8Pl8Bvmx2WyG1qe0tHTLTSILMY2laRpaRGbu/xkgfuW2Z5q9xYv33+1DdJq/tQYCAb73ve/x2GOPZYy0eL1e0zq6i6LIwkLyuHxrEOmzZ88aehsd9957L88880xOdhP5xI4jO5mepmVZpq+vj0AgQHt7O6WlpeuOY7FYiMfjps9vKwXK8/PzdHd34/P5OHz48IYXoXyRHTOPX1VV5ubmcLlcqzYK3AjyGdlJFSLnW5+jR/NmZmZob2/H4/Hk5XtWK21/c/JN5mJz2ESb4SclCRKqoPLKxCssxhfx2NLn9Nrsa8xGZ6lwVhjpJqfkZCY6w/dvfJ+P7v9oXo5hu2GpqMDzH/4Dwb//B+TRUdA0pF27kJr2EpMTqG43lt27URcXifX0IDocWJua0saQ9uwh9vpZtDIfgu5rNL+A4HJhqTDPxkK/nuvr69mzZw+KojA3N0cgEGBoaIhoNIrX6zXIz1ZEfQqR7ABE/98bKCPBtNdiV+aZ//vL+H77oOnfp/tK7d+/f9X3bFZgnrp2Pfzww7z73e/m8OHDq75/cnKSqqp0w92qqipkWcbv92+6gspM7DiysxzBYJCenh5sNhtnzpwxHF3XQ75JidkNp5aTCF2fk00Ua60x80F2EomEKWPpbcpFMelYbsYTpZkC5VT9z/KOyPkkOolEgvPnz5NIJDh16tSmCWC2SK1kDGtJUatA+jGKiCiawnxkHrfkTtukroevIwpimq5GFERERK4tXtuCI0hiO5rB2fbto/TzjyKPjYGqgWQh+soryejO5CSCKGLxetFiMRLXhpNpsZRzZ927F2VigsT1UQTJAooKViv2I3dsKIW1HpZvlhaLxYj6AIbWZ3Z2lmvXrhlRH5/PR2lpqelNWqEwyU5iJowyHFz5Bw1iQ/PI/ojpKa1siIwZDQUBPvOZz3D+/HleffXVdT+zfD6FWNEHO5zsTE5OcvHiRerq6oxGRdkin2QHbjuqmzmuvpkODAwwOTm5IX3OamPqAlqzLkyzCNTk5CQXLlygoqKCaDRqWug8HwLlrRQih8Nhuru7cblctLe352VzyQatpa3J1BUyVuF2qFrWZHx2H+X28rRUnqZpeK1eVFZeGyoqZY7cr+NcsB0LsWCxYK1PmpkmRq6DooCUHuYXnU7USCT5t5TrSHQ6cd55J9aGGygzfrBKSLW1WEx+cl6PWLhcLlwuF3V1dSiKYmh9rly5khb18fl8FBUVmXKeC1GgrATW9hSUZ6Omk52WlhYEQWBgYID77rtv1fdttsfOn/7pn/L666/z4x//mN27d6/5/urqaiYnJ9Nem56eRpKkTe1N+cCOIzuCIKAoCpcvX+bmzZu0tbWtCKNlg3wKlMF8sqNHTN58801UVd2wPme1McHcJ93Nkh1N07hy5QrXr1/nyJEjqKrK8PCwKXOD/HhjbUX/HEiK73t7e6mpqWHfvn3b+uS037ufU1Wn+MnkT4hpMURBRFEVBEHgowc+SpGzyBA5x2IxIpEIp8pO8fbC28xGZ/HavQgIzMfnsVvs/Nyun9u2Y9kOiO4iBKsNNRpJ+x3VpSUstbWQYe0Q7Haszc1YmzPbYJiBjawFFovFSGdBkojrVhbXrl1L81baTNSnEAXKYunaGQSpzPxoq8/n45577uHrX/86n/zkJ1fodubn5zfUhmM5NE3jM5/5DD/84Q959dVXaWxsXPcznZ2dPPfcc2mvvfDCC7S3txeUXgd2INmJxWJ0dXWRSCTo7OxctSRuPeRLoKy35Dd77HA4TCQSobS0dE3vp40gVYth1pPTZsiOLMucP3+epaUlTp06RXFxMdPT06b2szAzsgPJlJIsy1gslrwuyOPj4wwMDNDa2rru09ZWQBAE/q9T/xd/3ffX/Mv1fyEmx6h2VfNb+3+LX274ZaNiKxgM0tvbi9frZV/TPkK2EP/zyv/EH/ED4La6+Y2W3+BQ6aEtm3shdL4VfT6k+jq03vOIkTBqOIy6sIAgWbA1N23b5r6ZBx896rN7924j6hMIBLh69SqRSISSkhKD/Gwk6lOIaSyp3Iml0Z3U7KReTgLYm715q8p66qmnuPPOO+ns7OQLX/gCbW1tyLLMiy++yF/+5V/S09OT8bzG43Gj9008HmdsbIyenh7cbjfNt8jzJz/5Sf7+7/+eL33pSxQXFxsRm5KSEuPB+tFHH2VsbIxvfetbADzwwAM89dRTPPzww9x///2cPXuWZ555Jq13TqFgx5Gd3t5eHA5HmqFlLshXGktf5M0cWzcvtVgstLW1mbYQpppJmoVcyU44HKarqwubzUZnZyc2W7Kc2MxIjD6eWRULxcXFhki4oqLCKNU1M6KnaRpXr141LDEKKTTslJx86sineODwA4TlMMW24rQeO4FAgN7eXurq6mhqSm7gv9LyK9y5+056pnvQNI3DpYcpsZUgy/KW2lhsd6RAEEXsx48jxOMI3d1ooRCWMh+21lakHNsqmAGzUkapUZ+WlhYikYih9RkeHsZqteLz+YyU11r3TCGSHU3TcN5XT+JfxokNzRuv25uT1Vj5QmNjI2+99RaPP/44n/3sZ5mYmKCiooLjx4/z1FNPrUpWx8fH0/ynnnjiCZ544gnuuusuXnrpJSBZRg7pRpwAf/M3f8Nv//ZvAzAxMcHo6GjafJ5//nkeeughvva1r1FbW8uTTz5ZcGXnsAPJzvHjx01xYM0X2dHHNmODVlWV/v5+pqenOXjwIAMDA6Yu0vpYZp6HXMjO7OwsPT091NTUsH///rSFbbtc1FdDqkanurqaqqoqFhYWjJb8kUgEn89niDqz9SPKBL3kfnFxkY6Ojk2FqPMJm8W2otfNxMQE/f39GSNRZc4yfn7PzwOba2iYKwohsgPJtJR48CARScJ15AiC04mwxWXdy5GvlJHT6WT37t1G1GdhYcFId/X19VFSUmKQH7fbnZ7aK0CyAyC6rPh+++CW9tkBqKmp4cknn+TJJ59c8bfVikMaGhrWlW3IsszCwgLj4+OrVmB94xvfWPHae97zHrq6utaf+DZjx5Edq9Vqyuacb7Kz2bGj0Sjd3d2GJUKqkaNZ0J+gtzOyMzo6yuDgIPv376dumbliLuNlM79cN7vVhMg+nw+fz0drayuhUAi/38/MzAyXL1/G5XIZxMfr9Wa9aOtdwAFOnjxpRLoKHZqmMTw8bGiuMhnQpiJTabtOfNZqaPjTAk3TEGw2xAIhsltRqWaxWIx7Ro/66Fqf69evp0WFSktL0TRty3v7rIfUNUQqd24JyckGm/39FEUpuHNtFnYc2TEL+RIo62NvhuzoXaDLy8s5ePAgFouFaDRqbARmLvbbRXZSq8pOnDixauMqM/vi6OPlcrzZGnnqnWl1F2q9Jf+FCxdQVZWysjKD/KxGYILBIN3d3Xi9XuP33wnQf9PZ2Vna29spLi7e0OdTS9v18XRyaXbUZ7vTWKkopLlsRxTF6XSya9cudu3ahaqqhtZneHiYvr4+JEnC7XaztLS0IuqznSiUeaTCjNLzn6aHiVTsOLJjpl4lH+RBHzsXsqNpmqHP2bdvH/X19Wn9LsD8i9HsCFc2ZCcej9PT00MikVi3qqwQIju5Wj9IkkRVVRVVt+wCFhcX8fv9jI6O0t/fj8fjoby8nIqKCmMR14lRfX09e/fuLcgFNRN0F/p4PM7JkydN6f2zWkNDPZWYa9SnUNJYsD09f9bCds9HFEUj6tPc3Ew0GuXChQtGYYoeFdK1PoVW8VMI2Gzp+c/Izk8ZdEGcoigFQXZS9TmZIh35LGnfysjO0tISXV1deDyeNb3L8jW/jUaKzCotFwSBkpISSkpKaGpqIhaL4ff78fv9jIyMIEkSTqeThYUFDhw4kLP315ZDU5FnLjN35U32WkRKm0+AzfwNKNuoj67nWy/qUygEo5CIF2w/2VkOh8OBw+GgpKSE3bt3G1qfkZER44FBJz/FxcVbNvdCO086zIjs7JRI8kbxjiU7qeTB7KeDjZIdXZ8DcObMmYxPxfqNtRO8rFYbb2pqivPnz9PY2GhU56yH7UpjpQqRwfyOyHa73QjdK4rChQsXmJ2dxWazcenSJaampowKr832U8obNBUu/zN2fz+7BBCxIAz/C8rcAPHmD4KYv+VltahPKjnV35dKgKCwCEahbZqF+GSvz0kURUpLSyktLTWiPrrWZ3R0FFEUjYhPWVnZOzbq87PITmbsOLJj1sKgL375aiyYLdmZm5uju7ubioqKNfUZgiDsCJfyTONpmsa1a9e4du0abW1tVFdXb3g8szaFbNoCLBcim1H9txpkWebChQtEIhE6OztxOp2Ew2FmZmaYmppicHAQl8tlEJ+SkpKCWYxC17vw+PsQLDZEe5KQaaqMZf4alpmLKFVHt2Qeq0V9UgXPQNZprq1EoZGdQpsPrL4BOxwOamtrqa2tRVVVFhYWCAQCjI6OMjAwQHFxsSF0NjvqU4jnCX4mUF4LO47smImtdihPRao+p7W1lbq6unUvUrP79+RjzOVkR49azM/Pc+rUqQ0bVurnxKzFZb3ITq76nFwQiUQMX7eOjg7jSVQXOTc0NJBIJAgEAszMzNDb24umaYbAuaysbNuqtG7evIl1tAufTUSwp0SeRAnkGJbA4JaRneVYK+oTi8VIJBIoioIsy3kpbd8ICm3TLLT5QHbRhtSoj54m1vv63LhxA0EQ0rQ+P83YbGTnpzUi9jOykyd/rLXGVRSF/v5+w7E6G5d2fVyz01hmj5lKJiKRCN3d3VgsFjo7O7M2aU2F2amHtQTKW0l0FhYW6OnpoaKiYkVvoVRYrdYVIueZmRmuX79u9CfRyc9WVKrodh43b97k7spSxOACK86mIICan0rHjSI16qOLXT0eD16vd0MiZ1lLEJD9xLUYDsFJqVSe1kAxVxQauSjENEYujQ7tdnta1GdxcdFId/X39+P1evF6vTmv/4WUCk3FZq+nQvz9zcI7muzkyzJiLQKRjT5nNeQrspOPNFYgEKCnp4fKykoOHjyY8w2U+oRulut5poVqKz2upqam6Ovro6mpKa3ibj2kipx1zYIuctYdqHXi4/P5TA9Hq6rKxYsXWVhY4OTJk0jBIQhdB1UB8dZ3aSqgoXrX99XZSiwtLdHd3U15eblBLrNtaBhUFrkUOc+SugAknd69Fh/7nUdwiJvTUxUa2Sm0+cDmGx2KomiQGz3qMzMzQywWM1p6WCwWJElCkqQN3Y8/bfiZQLmAYOYFls/ITiwWW/H6ZglAPiI7+UhjAZw7d47W1tYNbeZrjWe2eaeOfAuRU6FpGiMjIwwPD3P48GEqKys3NZ7D4UjrSjs3N4ff7+fSpUvE43Gjk3NFRcWmS8ETiQQ9PT2oqsrJkyex2+0ojoOo/j7E0ASaAkkaoKI6ypArj2zq+8yEbluxZ88eGhsbjd83m4aGmqYyGL/AojqPR/RiES3ImkxAnmE4dpkDzs0fZyFtmoXoMG52tMFut1NZWcnk5CQulwubzYYsy8TjcaLRKKIoGsRntY2/EEkh/CyysxZ+Oo8qS+TT+TyVQGiaxvXr13n77bdpaWnh8OHDOV1Q+YjsmEmgVFXl6tWrABw9epQ9e/ZsekFI1eyYgdQ0lk5ylpct5wN6a4EbN27Q3t6+aaKzHBaLxYhavPvd7+bUqVOUlpYyOTnJq6++ytmzZxkaGmJ+fn7D5zIcDvPmm29itVppb2+/nY602Ii1/hqJXe9Cc5ajOUpJ1Jwitv8jYM3NoNdsTE5O0t3dzb59+9bsWySKIhaLBavVit1ux2azIUkSYSHIkrqIiyLQbrWq0EQcgouAPENUjWxqfoW2aRaiw3g+N2C98MNut1NUVITb7cZms6GqKuFwmKWlJSKRCIlEYsV9s13naXJykk9/+tO0tLTgcrloaGjgvvvu4wc/+MGq93ZfXx8f/vCHaWpqQpIkvvKVr6x4z9NPP80HP/hBGhsb8Xg8dHZ28t3vfnfd+bz88sucOHECh8PB3r17DY+tQsOOi+yYia3Q7Oj+RnpX2Wz1OauNW6il5/qTfzQaBcDr9W56TLhNQMyO7KTqc/JdpZNIJOjt7UWWZdMa7q0FQRBwu9243W5D5Kx3cu7p6QFIEzmvJUhcWFigu7ub6upqWltbVy7wkgN5Vyfyrs48HlFuuH79OlevXl3XtkLTNEJyCItgwSkl01J61EdABEHDKtoAwYgECppAQksQl2NYLbacr6FC034UGvmCrY02CIKA1Wo17gldyL486rNd6Z6RkRHuuusuvF4vX/ziF2lrayORSPDCCy/wqU99ijfeeCPj7xcOh2lsbORDH/oQjzzySMaxd+3axWc+8xlOnTpFcXEx3/zmN7nvvvvo7u7m0KFDGT8zPDzMBz7wAe6//36+/e1v89prr/GJT3yCioqKgjMD3XFkZ6eksRRFMQS6oijS2dm56U2uUEvPg8EgXV1duN1uTp06xUsvvVQQTuqZoGt2tkqIHAqF6OnpoaioiGPHjm3LAmm1Wqmurqa6uhpN0wzj0uHhYS5evEhJSYlR2l5UVGScj+npaS5evEhzczP19fVbPu9coWkaly9fZmJighMnTlBSUrLqeyfDk/TN9jEdmUYUROrcdbSVtVFsS1pduC3FOEQnMSK4LG5j/FAihlN0Y8eZFhncqH9XoZGLQpsPbG9qzWKxGJEfPbUpy7JR2acoClJcRYwpiEV2hKKNF2FsBA8++CCCIHD27FmKim5HTw8dOsTHPvaxVclzR0cHHR0dAHz+85/P+J5f/uVf5uLFi+zdu5fi4mL+y3/5L3z961/nJz/5yapk5+mnn6a+vp4vf/nLABw4cIBz587xpS996Wdkp5CQT4FyNBrl7NmzVFVVceDAAVNuVrPFxPqYmzkHekl0fX09LS0teWl+aGZjQUEQiEQiLC4u5r3jaiAQ4Pz589TW1qadm+2EIAiGWFM3YdRFzlevXsVms1FRUYGqqkxMTNDW1mZ6yi2f0EXUi4uLnDx5ck3X+dnoLK+Mv8JSfAmf3YeiKfQF+liML/Jvdv8bbBYbdtHBLnsD16KDLMrzWAUbcS2GRZTY62rBITnSyHMmkbP+35lQaOSiEDUbhTKn1KhPKBRC0gSEi5MwF0EFVEArdSIcrkVy2Ez/XQOBAN/73vd47LHH0oiODq/Xy9LSkimaHUVR+F//638RCoXo7Fw9anv27FnuueeetNfuvfdennnmGRKJREGVse9IsmPW5pePSImmaczOzhIKhTh06FBGJ+9ckY/5WiwWEonEhj+ni22vXLnC4cOHqampMf62Xeaia0FPP3g8HpxOJ+fOnTM29vLyckpLS02NuoyPjzMwMEBrayu7d+82bVyz4XQ6qauro66uDkVRCAQCDA0NEQqFEEWR8fFx4vE45eXleU+/bRZ6ulBRlKyc4q8tXGMhtkCDp8F4rchaxM3QTcZCYzR6khVle+xN2EU74/EbRNUIZZZKau31lEtVGb3rUhsarlfaXmhkp9DmA4WpIwIQL03D3DLN1lwE5cIY0QMVaSJnM8jalStX0DSN/fv3Z/x7ahPUXKBpGoODg9x5551Eo1Hcbjff+c53OHjw4KqfmZycpKqqKu21qqoqZFnG7/en7QvbjR1JdsyCxWIhHo+bNp6uz5mZmcFut5tKdKBwSs9TdUgnT55ckSYoNLKTWmXjcrk4evQoqqoyNzfHzMwMAwMDJBIJfD6fQX5y6Qmkf5feh+bo0aOUlZXlPO/twNjYGJqmcebMGVRVxe/3MzExwaVLl3C73YbWp6SkpKA2IL2lg8PhyDpd6I/4cUnpkR9JlECDYCJovCYIAjW2Oqqtu9HQEIXVN661GhpmivoUGrkotGos/SGlkOYEQCQBgfCKlwXAMh9FQkIRReLxuBEt0YmPxWLJ6TffLJnJZvw9e/bw5ptvEg6H+cd//Ec++tGP8vLLL69JeJbPJ9/zzBXveLJjFnlI1eccPnyYgYEBU8ZNRSEIlJf3CcpECvJh3pnreMutH1KbzOkbt6ZpBINB/H4/Y2NjRqt5nfhkm+5SFIWLFy+ytLTEyZMnM4aaCxWxWIyenh5EUeTkyZNG+Lm4uJjGxkbi8bghcu7u7kYQBKOsfbvdp4PBIN3d3fh8vg2ljIttxUyEJ9JeUzUVDQ27ZeV1LQgCAtkv4KnXmn79Lo/66FU+iqIUhJ1FofVZSfU4KyQIkbWj4WJURiouXqH10X9vnfhIkpT1semp8IGBAe67774Vf98sydC7J7e2tmKxWGhvb+ett97iK1/5Cn/5l3+Z8TPV1dVMTk6mvTY9PY0kSQX3oLcjyU6hpbFmZ2fp6emhurqaAwcOEAwG82ZDYXap/EaIyfz8vNGY7dChQ6vepPmI7OTye2crRBYEgeLi4rSN3e/3MzMzYziSp27smTaD5WRhu2wccoFOFrxe76q/q81mo6amhpqaGsOHyO/3c+3qEFcuLlDiceMpq6Gsahcul2vLnurm5ubo6emhvr5+zdLyTGj0NDK8OMxMZAafw4eqqUyGJilzlLGryFzX+eXaHV0TNTk5yYEDB1ZtaLjVKLRIU6GSHc2x9tYpuG7f/6tVeMmyTCwWyzrq4/P5uOeee/j617/OJz/5yRUPU/Pz85t66EjtNaZD07SMPeN0dHZ28txzz6W99sILL9De3l5Qeh3YoWTHLGxWoKz3zxkaGuLAgQOGNiOfVV5mpt30MbOZ6/j4OH19fbS0tKzbP6cQ0libqbiy2Wxpreb1dNfg4CCxWCwt3eVwOFhaWqKnp4fS0tJNdYveDugN9+rq6rJ2otd9iHwukVZvFDmkEgqFWPD3MzDST9RWRnl5BRUVFZSWlubtfExNTXHx4sWcdVG73Ls4VX2KXn8vN4M3EQWRCmcF7VXtFOW5T9DY2BhDQ0McOXIEn8+XFoHciI2F2Sg0fczyiGyhQHVI4CuCQGjF34SyojWrsnRSAxi/taIoRjfntaI+Tz31FHfeeSednZ184QtfoK2tDVmWefHFF3n66ad54403Mn5nPB6nv7/f+O+xsTF6enpwu900NzcD8J/+03/iwIEDlJWVEQwG+bu/+zt+9KMf8a//+q/GOI8++ihjY2N861vfAuCBBx7gqaee4uGHH+b+++/n7NmzPPPMMzz77LMbOJtbg3c02dkMKdFTFoFAgI6OjrS+MnrY2uynpO0oPdfLeG/cuMHRo0epqKjY9JgbxUbSWPpmYZb1gyiKhnOypmmEQqE0HYvD4SAajVJbW7umx1UhYmJigv7+/tzIghJHWBhBlKNYiyvxFgt45Qj1iQizQgUTC3H6+vqQZZmysjIjZZirFmo5RkdHuXLlCnfccUdW1+Rq2OfdR527jrnYHKIgUu4oT+p28gRN07h27Ro3btzg+PHjK9YNuC1y1q/jrYz6FJo+JtWxvtAgttWiXRxHm71NeISyIix3ZH8vZRP10YmPxWKhsbGRt956i8cff5zPfvazTExMUFFRwfHjx/nqV7+66veMj4/T3t5u/PuJJ57giSee4K677uKll14Ckg8P//N//k8+8YlPUFJSwh133MG//uu/8r73vc/43MTEBKOjo8a/Gxsbef7553nooYf42te+Rm1tLU8++WTBlZ3DDiU7Zl34uZKHcDhMd3c3kiRl1K3oi5aiKEiSeac4X6Xnq42ZSCQ4f/484XCYzs7OrDUo25XGSiU5+ufMXCSXN+sbHh7m6tWreDwepqammJmZMdJdZWVlBaV9SIWmaQwPD3P9+vV1G+6tBiG2gJgIoTnKksafAFYXohKjzKFRuutgRi2U2+02omIej2fDv48uAB8bG1u3h062cEpOo5lgPqGEQgy98Qb+aJT2u+7C7XZnfN9aIudM17eZUZ9CTGPls7N5LjCiTTYJ4cQetFAMLRxHcNk23Wcnm6hPWVkZX/7yl3nyySfTPqsTpExoaGhYVwLx1a9+lRs3bnD48OFVz/c3vvGNFa+95z3voaurK4uj217sSLJjFnKxi9D1OTU1Nas+yeeL7OSr9DzTmKFQiK6uLpxOJ6dPn95Q/nU70lirCZHzAVVVuXz5MpOTk7S3t+P1elFVlfn5eWZmZhgaGuLChQuUlpYaG7vTmf/NNBuoqsrAwIDR0bu4uDjHgWQ0hNtE5xY0UQIlmWpdTQvl9/sZHR1FFMW0Ts7r3SuqqtLX18fCwgIdHR07RgCuKQrB7/4rk//7fyMsLtJUXoYyNY36oV9DXOf8p4qcYWVpe2rkw4x0VyFGdgppPpkg5KmZYKaojx75yRT12ayOVVGUvDdZ3U68o8nORjQ7qX1lUvU5maA/ieQj5bQVaSy/309vby+7du3KbBGQw5ibwXpprK3siCzLMufPnycajXLq1CmDxIiiiM/nw+fz0draaqS7pqamGBwcpKioyCA+21W2rc89Fott3rZCciQLBVQZ9LSPpiWJjitzWmm5Fmp+ft5oZqiTQ538LCcysizT29tLIpGgo6PDtHTYVmDphReY/uY3UW1WvA17IBoj/NJLqOEQ3k98YkPXwkZL2/X/zhaFptkpRLKzXRYfetTHZrMZv7ssy0bUR4+A53rOCvFcm4kdSXa2Oo2l63Pm5uYy9pXJNL9CN+3UkUpMUgXXBw8eZNeu3CpStjKNlRrRyTfRiUQi9PT0YLfb6ejoWDPaVVRURFFREXv27DG8qWZmZlaUbWcT0TADessAfe6b/U7N5kF1+BDDfjSrEwQREhGQnKjO9dNiqeRw3759hMNhI+ozNDSE0+k0zpHT6TTOe3t7+5acL7MQCwYZ/6fvYLFZ8TW3IIgiuIoQrFbiFy4iX7+OtaEhp7HXi/rkInIutDRWoUWaUrGd50kQBKNpIST3qHg8jizLhEKhtL9n29fnZ2Tnpxg62VnrBk/V53R2dmb9RJkvYpKvyI7uyj0zM7NCcJ3rmGbPcTlSNQz5JjoLCwv09PRQWVlJa2vrhhaFVG+q1LLt1IiGHvVZy94gVywtLdHd3U1ZWZlp1iWIFtSSRpBcCNFZ0FQ0VwVqURVYN34MLpeL+vp66uvrkWWZQCCA3+/n/PnzJBIJHA6H0eV5p5CdSCRC98svUxWNUlxTmyQ6tyC43SjT0ygzMzmTneVYHvVJ/V+2IudC2/AKbT6FilStj8PhWBH10dNda/X1KbQeS2ZjZ6waeULqE1GmH1lP56ylz1lr7J0Q2dF1S2+++SaqqppiWJprX5zVsDyNlW8h8nJMTk7S399Pc3MzdXV1m67uKi0tpbS0lJaWFiOiMTMzw+XLl3G5XGnprs0u9DphaGxspKGhwdzzZLGienaDuwbQbqezNglJkqisrMRmszE1NUVtbS0Oh4OxsTEuXbpEcXGxEfXJt79ZrlhaWqKrq4uq3bsprq5GDYXS9DlaOIzgcCBu4qFiLWRKd+n3zFpRn0KL7BQi2Sm0c6RDn9fyqI+qqmkVXqtFfXTNTi5YWlpicnKScDhMIpGgqamJ0tJS4++JRIKbN2+yuLiILMuGh1eq9UUsFuP3f//3efbZZ4lEIvz8z/88f/EXf2Ga3c6OJDtmprEgqQdIJTup+pxc0zn5KhM3e8xwOIyiKDidTg4fPmwKs89nGmsrhch61dLIyAhtbW2bKnFeDcsjGnq6q7e3F4CysjIj3bXRJl03b95kcHCQgwcP5tejRjT/aVB3XG9paTFsV5qamojFYsY50kXOOjn0+XwFEfXRGx3u2bOHxsZGgu++TvCf/gklEED0eNAiEZSpKexHj2Btasr7fDKlu1aL+pj9MLVZFJqGaCdCFEVsNtuqWp+pqSmKioqQZTnn9VS34ikvL+fq1atpf9MrKAVBoLm5GVmWuXDhAr/zO7/D97//fUOf95nPfIbnnnuOv/u7v6OsrIxHHnmEX/qlX+Ltt982ZV/a/pVhG6E/0aTe7LIsc/HiRebn57PS56yGnRDZmZyc5MKFCwC0tbWZRhzylcYys3/OetDTenofpZyrljYASZKoqqqiqqoKTdOMdNfw8DAXL17E6/UaG/talUip/lzHjh3D5/OZO9FEGGnyHJa5IRBElLIDyFXHwWJO1+gbN24wNDTE4cOHVziu2+32FSJnvQIuEong8/kMkXM+UoLrQSdp+/btM55I3e//BbRwiMjrZ5HHbiLa7TjaT+D59/8+LbW1VVhN5LywsEA4HDaal251Q8NM+FlkJ3tkM6/lUR9ZlikqKmJpaYlwOGxcGx6Ph+Li4qxJRklJyap7ZSwWM4yxnU4n0WgUn89HOBzm2Wef5eMf/zgLCws888wz/I//8T9473vfC8C3v/1t6urqePHFF7n33ns3cCYy4x1NdgRBSCMl4XCYrq4ubDYbZ86c2VTL/60sE98o9M3w+vXrHDx40CA8ZiFfZGerKq7i8Ti9vb2oqsqpU6e2pfJHEAS8Xi9er5fm5mYikYiR7lou4PV6vWmbV19fn0HWTS/PToRx9P0PhEgAuBVdC01iCQwSO/AbYMm9RbymaVy9epWbN2+uaLiXCatVwKWmBHXik3qO8gU9zXb48OE0J2jBZsPzf/wfFL3vfchTU4jFHqS63QWxYernZGFhgQsXLrB3716jgeZWNzTMhEIkO4WKXEiYJEmGDczIyIjx+Rs3bhCPxykuLqa2tnbVnlDZIFNjSL2s/tVXX+XjH/84b7/9NolEgnvuucd4T21tLYcPH+b1119/55KdfHQlnpmZ4fz589TW1m5YgLrWuGZis6WFcLv8OBgMcvr0aRwOBxcuXNhUvjbTPM0Oh4dCIWKxGHa7Pa+bRCgUoru7m+LiYtPSembA6XRSV1dHXV2dIeCdmZnhwoULqKpKWVkZpaWljI+PA3Dy5Mm8kDRp8hxCNJBMXenu35qKuDSOxd+HUnU0p3H1SNrc3Bzt7e05La6pFXB6StDv96edI538mOldplcxDg8PrxlJs5SXY8mhgWO+MT09zYULFzhw4AC1tbXG61vd0DATCpHsbFfpeTbYzNqoqiput5uamhrDE2thYWHT59/hcGCz2RgbG2PPnj1GkcbMzAwTE0kj3snJSWw2W5rOB6CqqmqF0Wiu2JFkx0yIosjNmzeZmJjg0KFDaTf7ZpCvyA7kvgDokSu73c7p06ex2WzG4mV2JCaRWNsVOBvo1g8+n48rV67w6quvGqmciooK09MUuk/U7t27aW5uLogn70zQBbyVlZVomsbi4iITExMMDg6iaRolJSVMTEwY6S5THw4Cl5P9dFKvP0EEZCzzV3MiO6n9fzo6OjYtkIeVKcHFxUX8fj83btygv78fj8djRMbcbnfO50jTNIaGhpiYmODEiRN4PJ5Nz30rMT4+zsDAwIpoFGx9Q8NMKNTS80JcGzZLwlILdQRBwOFwmHIviqJIU1MTIyMj9PT0AMlWGHfddRd+v3/Nz5qZMiy8q2gLIcsyiUSC6elpTp48aRrRgfxZOwA5kajZ2VnOnj2Lz+fjxIkTxpOtfiFtt3HncuhPlIqiUFZWRmdnJ+9617uorKxkdnaW119/nddff52hoSHm5+c3faOPjY3R3d3Nvn37aGlpKcjFLBP0eU5OTrJ7927e/e53U1tby9zcHG+88QavvfYaly5dYnZ21pzfWFgj0pXDOYvFYpw7dw5N00wjOiunJVBSUkJTUxOnTp3izjvvZNeuXSwtLfHWW2/xyiuvGG0XNnJv6SnD6elpOjo6dhzRuXHjBpcuXeLo0aMriE4miKKI1WrFbrcbgtfUbvGyLBu9XsxaTwpRoLzdkZ3JyUk+/elP09LSgsvloqGhgfvuu48f/ehHq56rvr4+PvzhD9PU1IQkSXzlK19Z8Z7Uh+jHH38cQRD4zGc+s+58Xn75ZU6cOIHD4WDv3r384z/+44r3FBUVcejQIY4ePUpraytVVVXMz8/T2NgIQHV1NfF4nLm5ubTPTU9PZ3VtZoN3bGRHT1cANDc3m+Kxk4pcrCjWQ6ouYyMYHR1lcHCQ/fv3G5UtOpbrlsya52YWu9WEyE6nM2Plkv60kEujvryLefMMXRDb3NxMfX09ALt372b37t0oimKku1JNOXWRcy6pHKVsP2JoEjT1dhpLVQABxbdvQ2Pp92BJSQmHDh3asid4u93Orl272LVrF6qadLX3+/2Gq302Nh+KohidtHdaR+dUb7RstFGZkI+GhplQiGks2L7IzsjICHfddRder5cvfvGLtLW1kUgkeOGFF3jkkUc4f/58xs+Fw2EaGxv50Ic+xCOPPJLxPfq5fuutt/irv/or7rjjjnXnMzw8zAc+8AHuv/9+vv3tb/Paa6/xe7/3e+zfv5+PfvSjK94vSRJWq5VEIsHFixd58MEHAThx4gRWq5Xvf//7fOQjHwGSpqMXL17kv/23/5bt6VkTO5LsbPZC00t7d+/ebdT7m4189MTZaGdm3QdpamqKEydOrLqRb4eX1WrI1vpheZpCr8rRG/X5fL6sNqyLFy+ytLSUHzFvnnH9+nWuXr2asWoJktegnvLTNI2lpaUVqRz9HGWbypGrT2AJDCIGJwCdzAsopS0ovgNZz31hYYHu7m527dq1rSlDUbztap/ayVm3+cjU9yiRSBidsNvb2zfcEmA7kZp225Q32jKY0dAwEwqR7CyP7MzOzjI3N0dpaSllZWV5/e4HH3wQQRA4e/Zs2np16NAhPvKRj6x6H3V0dNDR0QHA5z//+YzvUVWVSCTCb/7mb/LXf/3X/PEf//G683n66aepr6/nz/7sz4jFYuzZs4fvfve7fPWrX+XDH/4wFosFu91OIBDAarVis9lYXFxkamqK9773vYYguaSkhN/93d/lkUceoaysDJ/Px+///u/T1tZmVGdtFjuS7EBy499oOFHTNK5du8a1a9cMfU53d7fp2hpIbjSrOdBudtxsiEQ8Hqenp4dEIkFnZ+eaRpSFQnZy7YgsCILRqG/fvn2r+lJVVFQYTtvRaJSenh4sFgsnT540VbCab2iaxuDgIJOTk1k7fwuCgMfjwePxsHfvXmKxmFG5NDw8jNVqNSJjpaWlqwuzLTZiB38Ti/8ilrmrIIoovn1JopNlvx1dWJ0ajSoECIKwwuZDj4z19vaiaRqlpaUsLi7idrs5cuRIwQjYs4GmaWkmsPki97k2NMyEQiQ7kJx7JBLhO9/5TlpfmaamJn71V381L8a/gUCA733vezz22GMZf7vNeu6pqspnP/tZfvEXf5H3vve9WZGds2fPcs899xAOhxkcHATg9OnT/O///b85f/48VVVVNDY2Gk0FE4kEkiThdrv50pe+lDbWn//5nyNJEh/5yEeMpoLf+MY3TLvHdizZ2Sj0RkYLCwucOnXKyK/nQ0icz3Gziezo3Vs9Hg/Hjx9fN6Wz3WRHFyLrx7XZ0vLlG5a+qXd1dSGKIl6vl0AgQHl5+ZamT8yAoihcuHCBUCjEyZMncxZpp6ZyFEUxUjkDAwPE4/G0dNeKFI3FilJ1DKXq2Ia/9+bNm1y+fJlDhw6ZlovPF6xWa1r0cGpqiv7+fkRRJBAI0NXVZVR3bUbkvBVQVZWLFy8SDAbzpo3KhNXSXdmWtheiQFl/yP7Od77DtWvX0v527do1vvOd7/Abv/Ebpn/vlStX0DQtreuwmXj++efp6emhq6sr689MTk5SVVVFcXEx7e3tQPJBW1EU9uzZYzQz1e8jSIqTh4eHVzxgOhwOvvrVr/LVr37VpCNKxzuC7OjaALvdvqJ/Tj60Nfq4+SJRaxGJqakpwx6gqakpqwV4OzU7yzsi6+WsZsFqtRp9JFRVZWRkhGvXrmGxWJienkaWZSPqU+i6i1gsRk9PD6IocvLkSdPSJxaLxdi0W1tbCQaD+P1+xsbGGBgYMMWeQY+qjo6OcuzYsRUlphuCEktWhFnsOYmic8Hi4iKXLl2irq6O5uZmIzLm9/u5du0aNpvNOIc+n6+gIj6KotDb20s8Hqe9vX1bo5irNTRcbgGTmrIvxDTh3Nzcik7BcLtX1OzsrOkprdQ1crW/57p2jo6O8qUvfYnvfve7GybCy79zvXluF3Ys2ck2jTU9Pc358+fZvXs3+/btW/GUsNMiO6uNm5qia2tro7q6Ousxtyuyk60+xwxomsaNGzcM64fKykpCoRAzd1fnxAAAzjlJREFUMzOMj48bnks68Sm0J/VgMEh3dzderzev0ShBECguLqa4uJjGxkbi8bgRGbt+/TqSJBnEJ9tNXdeOzc7O0tHRkXODMiG+hGWqB8vSDdA0VFcFcuURtKL8RohmZ2fp7e2lqamJPXv2AMmn0FQh+HKRs97JuaKiYsuiKJmQSCQMAb8uAi0UZBP1icfjSJJkWBkUQpRH1wiuhbm5OdPJjl4lOjAwwH333Wfq2OfOnSMQCHDmzBnjNUVR+PGPf8xTTz1FLBbLeK9XV1ev6IMzPT2NJEl51y9tFDuW7KyH1M3/8OHDq3oDSZJEJBIx/fvz4WO12rh6amN+fj4tRbeRMbea7Gwl0VFVlcHBQaanp9M0Lm63G7fbvWJTHxkZSdOw+Hy+bV1k9f4/dXV1WUfrzILNZkuzZ9jopp5atXTy5MncN345hvX6DxHCU2hSEQgi4uIo1ugciYb3ojnzs7BOTk7S19e3pr9YamRM07SMmjH9HG1WV7ERxONxoyP8TtAXLY/6jIyMMD8/T11d3bY0NFwL60UmNxW5XAU+n4977rmHr3/963zyk59M0+3o9jK5PkjcfffdPPvssxw4cMC4Tj72sY+xf/9+Pve5z6167XR2dvLcc8+lvfbCCy8UpHD/p5Ls6PqcxcXFdTf/fEVgJEnKi6ne8jRWJBKhu7sbi8WSs8WF2WRnuUv5cuQqRM4FiUSCCxcuEIvFOHny5KrCwdRNXX9Sn5mZYWBggEQisemS7VwxMTFBf38/ra2tprn/ZgUlhhiaTqaMrC5UVyWiKKVVLumb+uTkJIODg7jdbmNT93g8RtWSxWLZ9OJnWRxBiMygOcoMIbQmOREifixzQ8h5IDu6R9eRI0coz7LzsSAIBoluaGggkUgYnZz1CMtmzF2zRTQa5e233zY6gRdCRCRb6KXxN27cMBo1bkdDw7Xg8/loamri2rVraRkGQRAMy4184KmnnuLOO++ks7OTL3zhC7S1tSHLMt///vd5+umn6evry/i5eDxOf3+/8d9jY2P09PTgdrtpbm6mqKiI5uZm7rjjDmM9LioqoqysjMOHDxvjPProo4yNjfGtb30LgAceeICnnnqKhx9+mPvvv5+zZ8/yzDPP8Oyzz+bl+DeDnzqyo4f7HQ4HnZ2d625M2ykk3uy4c3NzdHd3U1lZycGDB3O+2bdKs2O2EHk96ETQ4XDQ0dGRde+d5U/qwWCQmZmZFSXbFRUVpnco1pHaC2Ujm60ZEKJzSFPdCLEF/RVUV3nS7NOaFERn2tRTheA64XW73dxxxx2b3tSF2MKtzs0pT5iCABZbkpSZCD0qfOPGjZz70OiwWq1UV1dTXV2d0dy1pKQkzdzVjGspFArR1dVFWVkZBw4cKKh07HpYXhqvRypW0/psh3+Xro351V/91RXVWHv37uVXf/VX8/bdjY2NvPXWWzz++ON89rOfZWJigoqKCo4dO8af/dmfrfpbj4+PGwJigCeeeIInnniCu+66i5deeinrqreJiQlGR0fT5vP888/z0EMP8bWvfY3a2lqefPJJfu3Xfm3zB2syBG2720HmCFmWV2zQuj6nrq6Offv2ZXWTj42NcfPmTU6dOmXq/Obm5ujt7eXuu+82ddzu7m5KS0uRJImBgQFaW1upq6vb1IKmj9nQ0GDKHOfm5ujp6eHnfu7njNcyCRDzuQjPz8/T09NDdXV1Rq1WrohGo8amHggEsNvtBvExy2wyVeNy7NixLXFcN6CpSDdfQ4j40ZzlycaBqowYnUUpacyqAkv//Z1OJ4qipLmRV1RU5FSWa5nuRZp469acUgwFI37UkgYSe35+w2NmgqZpXLp0iZmZGY4fP74pA8T1sPxastlsBvFZs/x/DeiVmDU1NTuqEzjcbqmgn/tsSuP19SQ16pMqkF0t6hOPx5mcnKShoWHDqdVwOIzVajUI/Fb22VkNiqIQDodzXiuCwSAjIyNpkZ18Qa/Gamxs3FI9209FZEdXwA8PD6+pz8mEnSZQFgSByclJQqEQx48fN+XmyrdmJ/UpbCvCzZOTk/T39+elj8tyYWomQ059w8olmpHqE7UpjUuOEKJzCNE5NEfp7Q7JooRqdSOGplDkKEirz8nv93P+/Pk0Ma+e7pqenuby5cs5aVhUzx7w9yHE5tHsJYCAkAiCYEHx7jXj0FFV1Sjr7+joyEuvlFRkupaWl//rEcZsroP5+Xm6u7tpaGigoaFhxxGdVCPYbM+9vpbko6HhWnNNhZ7a3W5stsfOTkp15oIdT3b0zWFpaYnTp09vmNlKkrRjyI7uHaKqKp2dnaYZYZqdckslO1tdcaWXN7e1tVFRUZG374KVHYoXFxcNgXNfX59hWqqnKNZDNBo1WiRsJO1mKlQFQVPRlntgCRZQE6Cu3qZBN5U8dOhQWjXg8r5HyzUs2dh8aA4vidpOpIk3k67rABYHcuURVE/DZo4YSK4jvb29yLK8LeXZy68lvVJwYmKCS5cuGXoovZPz8vtIrxhraWlZYQlT6NA9xhYXF2lvb98Uwc+2oaFuVJxrYqPQiKQZJqD5Xp+3GzuW7AiCYOhznE5nVvqcTMh3PxyzXFuDwaDRFK+qqspUx2+zrS10srOVREdRFPr7+5mfnze1DX620M0mS0pKaG5uJhKJGCmKoaEhXC6Xsal7vd4V52JpaYnu7m5DZ7FdT1ma3YNmdSLEg2j228J+IRFEc/gMzU7aZ1L0Rev5iy3XsMzPz+P3+w2bj1RfquXXuOptJO6uQQxNgKqiuSrS5pgrUquWTpw4sT0kMwWpeii9+6ze00e3qdCJT1lZGYFAgIsXL65ZMVao0KNp4XCY9vZ2U3tdrVXankgkDIKwXGC8HgpV+bHZyE6hV+ttFjuW7ExPT9PV1UV9ff2mctP5JDuQ3IQ3u3jqWqT6+vo03YtZyEc1lv4UpXdAzSfRicfj9Pb2oqoqJ0+eLIjmgE6nk7q6Ourq6tJMS3t7e4H0aMb8/LzRCHLb0w+SA6W0GctMH0LED6INQYmiWewopc23U1u3kKpx2SjJTLX5aGlpMXypZmZmuHz5chpB1H2pkByoJY2mHW4kEuHtt9/ecjPSjWB5Y8xUkfOFCxcAqKmpwePxmPZwtRXQmx0mEoktKVVOjfooipLxPC0nMqudy0I7x5v93X+Wxipg2Gw2Dh8+vKHmeZmQzw7KsDmyoz8x62aPNTU1XLlyxfS+QLq5oRnQNA2LxYIoirz55puUl5dTWVmZc+fd9aB3x/Z4PBw6dKggn06Wm5YuLCwYpqW6S3FNTQ3V1dUFsYiqJXvB4kRcGkVIhFGKKlE9e9Bc6RVhen+ncDhsisbF5XKtcLX3+/2GL5UezchVD7Ucupi3qqqK1tbWgjj360EURYMg2u12hoaG2LVrF5FIhJ/85CfY7fY0j7NC3cBkWaanpwdVVTl+/PiW92TRz0tqoUSmiE2mqE+hRnY2A0VRCvZaMQs7luyUlpaaUilhsViMvK6ZP7Z+Y+QaNdIduQOBACdPnjQa4eWjpN2sMfW0lSiKvPvd7zbEu+fOncNqtRqaBLMW4dnZWaP6bqub7eUKQRDwer2G7mJ0dJSamhpCoRCvvfZaRtPSbZgkanEtanHtqm/RjWYFQaCjo8P0zSoTQfT7/Wl6KH1Tz8XQUq8Y27NnD42NjTvi2tGRWhrf3t5urA2pgvm+vj5kWcbn863ucbZN0Ls6i6KYlXffVmE124PV/l1I+FlkZ30UxlW2jdBvNLOZrSAIOWthdKEqwJkzZ9IWKbP1NWaNuVyfY7fb00LvyxdhfaPK9Sn95s2bDA4OcuDAAWprV9+UCxG6IHN+fp6TJ08apD1Vm6Hrs1LTXYUStYpEInR1deF2uzl8+HDe56UTRK/Xu0IPdfXqVRwOR5oear37eHp6mosXL7Jv376tbdRoAjRN4/Lly0xOTqb1oYGVIuflHmdut9u457aLSCcSCbq6urBarQXf1Tn1/OhEJ/WhcKNan3zCDIFyIf8WZuAdT3ZS001mP53mogfSy0dXc+TOV2RnM2Qn1cwvkz5H37TLy8vZv38/S0tLhtdSatVSZWXluqkQvenY+Pj4umLYQoT+VJtJX7RcmzE/P2/oV3RrBn2z2i6/pcXFRbq7u7c19ZOqh1IUxUh3pZb/69fb8qKFsbExLl26xOHDhwvedX059P5Lc3NzdHR0rFmkkMnjTNeNjY6Opt2Ta1XBmYl4PM7bb7+Ny+Wira1tR0USBEEwekbZ7fYVcy8E4vMzgfLa2LFkx6wLKtVd12xslOyMj4/T19dHS0sLe/bsyXiM+Yjs5Ep29AZeG7F+EAQBj8eDx+OhqamJSCTCzMyMUbW0VhpH14jofVBySV9sJ8LhMN3d3RQVFdHW1rbm4iKKIj6fD5/PZ1gzpJYim+FEvh7E+atYR19GDI6D5GDJs5+ucTsNe1e/PrcaFouFyspKKisrjfJ/v9/P6Ogo/f39lJSUGJu6ngbbiSQ5tQdQLuXZNpttBZFeXgWnn6d83Fe6fYWurdtJRAduN+1zOBwrHorXS3dtxX2y2ciOoihb3m5hq7FjyY6ZyKdIORuyo4emb9y4wdGjR9fsD5MPYpZLBGp5R+RcK66cTqchStV7sOiWA6IoGsTH5XJx4cIFJEni5MmTBWcytx4WFhbo7u6murp6wxGR5aXIy53IU01Lc+28uxxiYAj7pb8DBAQ0kCMUz3Zzt7cW9rw3rYtxoSC1/L+pqSmtQ/HVq1fRNM3QAO0kjYKiKPT09JjWA2g5kdYfOPx+P0NDQzidToP4mKGv0yveSktLOXjwYEGQ5I1gLaIDG9P65PPYf6bZWRs/3UeXJbazi7Kew56enqazs3PdRniFENlJ1efonzfjJtZ7sLS1tfGe97zHCHUPDAzw+uuvk0gkjP4sOwnT09O8/fbb7N27l/3792/6XOmmpUeOHOHuu+82/I8GBgZ4+eWX6e3tZXx8nHg8ntsXaBq26z8ASBKdWxAEcEXHERevb2r+WwWHw0FtbS1WqxW73c6BAwewWq309fXxox/9aPPnaQuQSCR4++230TSNEydO5OXpW3/gOH78OHfffTctLS0oipJ2nsbGxojFYhseOxQKce7cOcrLy38qiU4m6BVeq5W2p/4vF0xOTvLpT3+alpYWXC4XDQ0NfOhDH+KHP/zhqp/p6+vjwx/+ME1NTUiSxFe+8pW0v6uqanhrpf4vm2rnl19+mRMnTuBwONi7dy9PP/10TseVb+zYyI6ZN812dVHWDfucTienT5/O6mbKBzHbCNnZqkaB+tOnLMuMjY1RV1eH1Wo1NBe6gWKu1ThbhevXrxutAyorK00fP1V70draao5pqRJDjMxk/JOGiGXhOmpJg7kHkgcoisL58+eJRqNp+qj9+/cb5+nmzZvGedKjY263uyA25VgsRldXFw6HgzvuuGNLNBWSJKWlBZeWltJEzhtJnwaDQd5+++0d6dMFuRGd5cgkck7FRqM+IyMj3HXXXXi9Xr74xS/S1tZGIpHgX/7lX3j44Yf5hV/4hYyfC4fDNDY28qEPfYhHHnlkxd91K59Dhw7x4osvGq+vd80NDw/zgQ98gPvvv59vf/vbvPbaa3ziE5+goqKi4MxAdyzZMRPbEdnR+4fs3r07a9NS2F6B8lZbP1y/fp1r166liUkzpSccDochcM7Waynf0E0NJycnOXHihFEenE+kilL37t1LLBYz9FDXrl0zTEvXTU+IEhoiApmuCQ1NMqGEWY5hufgPSEPfBU1FaXk/ctu/W9N3ayNIJBJGt+HlDesynSe9Cm5kZMRIC5aXl+Pz+bZFuFkIzQ5T9XV79+410qe6Jiq1WtDn86WJnBcXF+nq6qKuro69e/cWxD25EWyE6ESjUaLRKA6HY00t1UZL2zOdswcffBBBEDh79mzaQ15jYyMf+9jHVv3ujo4OOjo6APj85z+/4u862ZEkaUO9655++mnq6+v58pe/DMCBAwc4d+4cX/rSl35GdsyE3ql3s8gX2clETPRNfGhoiIMHD7Jr164NjZmv0vP1jj/VXC/fREdVVaMrbyaikGqgmNqdWPda0iMZ21WunSqkPnnypKnWHhuB3W7PaFp68eLFNU1LE4rGklBFhTaJmJLG0v9LKTu4uYnJUex//+8Qx94yXhJHXsZy8e+J/fr/k9GSYiOIRqN0dXUZVT/rXQN2u51du3axa9cuVFVlbm6OmZkZLl26lGbIWVFRsSW9akKhEG+//TYVFRWmpD3Ngp4+ra2tTasWHBoaIhKJGFYfdrud/v5+oyP4ToMsy0QikXWJjizLXL16lcXFReM1vfAim+q2jUZ9AoEA3/ve93jssccyRrO9Xu+637ka9NYrQ0ND1NbWYrfbOXXqFH/yJ3/C3r2rG+2ePXuWe+65J+21e++9l2eeeYZEIlFQ2sodTXbMQr79sXTo/VX8fj8dHR05XZxbHdnRc8v6d+ab6CQSCc6fP088HufUqVPrVp2kNp/TW+nrC/CFCxeMcu2t2qhisZjRMK2QhNSrmZYuL/8vLi5OpgmdbZRrMYgG0AQRNA3QiDf90qb9qKTzzyKOvZWmBwIQJ3qQer6F3PFAzmPrqWGfz5eTx5goioaLdWtrq1EFNz4+bhhy6ucxH1VwekRk165dNDc3FwzRWY5UkXNra6th9TE+Ps7S0hI2m414PE4gEMiq91GhQCc6TqdzXcKynOhA8ve7evUqra2tG/rebKI+Q0NDaJrG/v37V3zejKaCHR0dfOtb32Lfvn1MTU3xx3/8x5w5c4a+vr5VXd0nJydXtHCoqqpClmX8fn9BebX9jOywNdVYsViM7u5uw7E81z4pesdnMz1wViM7qf1z9PflE+FwmJ6eHpxOZ06u36mt9HWvpenpaWOjykm/sgHo1hWF7LMEq5uWTkxMcPnyZSRJwlq+i8myj1Amj2MJjYPkRK64A825+ZJty+Bzq/xFw3LpuZzJjl7xZhZRWK0KTk/jWCyWtF41m40i6l2dd2JExOVyUVRURDgcprW1FYfDwczMTFa9jwoFGyE60Wh0BdHRsbi4aKS1ckWmqE8qAVoe9TGjqeAv/MIvGFHotrY2Ojs7aWpq4pvf/CYPP/xwVnNNnVuhEfUdTXbMSmPlW6CsL8KlpaWb7jibamRnViOwTGRno/1zNov5+Xl6enqoqanZkIZpNQiCQFFREY2NjcZGlUm/km3X3fUQCATo7e3dUdYVOpxOJ0VFRYRCIfbu3Yvb7U6all7oA6C8vC6ZFrR6zFkwVAVY5b5Vc3vomJ2dpbe3l6amJvbs2ZP73NbA8jTO3Nwcfr8/remjnu7a6Ebn9/s5f/78juzqDBjE5sCBA8bT/PLeR6mi+UITg2+E6ECS7Kz3d7Maf+rnR18XL126xH333Wf8fbPkQl/rl+9Lej+woaGhVT9bXV3N5ORk2mvT09NIkrRqNGi7sKPJjlnIZxprbm6ON998k6amJlM8ePQL0kzdjp5u06NFWylEBpiYmKC/v599+/ZRV1eXl++w2WyGLiNVv6I/eabqfDZKIvX5t7a27siNanJykr6+vjTrjUympXrzOf1c5Wr8qTTfe0uvs4zwCCLKvvfnPP+DBw9uWdg8Nd21b98+wuEwMzMzTE1NMTg4uCGPM33+hw4d2rSx8XZgamqKixcvZuxKvbz30XIxuCRJpkbHcsFGiQ6wLpHJR4dzn8/HPffcw9e//nU++clPUlRUhKZpyLKMpmnMz8+vaJaZzdqd2kIkFbFYjIGBAe68885VP9vZ2clzz6VHal944YUtcbHfKH5Gdkhu9ma5fuvQNI25uTnm5uY4duyYaWXHqZEds6CPqSvytyqioxsajo6OcuTIEcrLy9f/kAlYrl9ZvqGn6nzWWrQ0TWNkZISRkZEtnb+ZGBkZ4dq1axnnn+pJpacF9ejY5cuXczYtlY/+n0h9/wCzQwhacqHVBBHN24B8bPWKkkwYHR3lypUr23r+9ShiUVERDQ0Nq3qcZbJmuHnzJpcvX+aOO+5Yt8dWIUJPEWc7/0xi8NTomE6my8vLcybTG4GiKCQSiQ0RHUiSGY/HkzGV5fF48mbn8tRTT3HnnXfS2dnJF77wBQ4ePEgwGOS1117jr//6r7lw4ULa+/WoTzweZ2BgwPjvsbExenp6cLvdRiT0c5/7HPfddx/19fVMT0/zx3/8xywuLvLRj37UGO/RRx9lbGyMb33rWwA88MADPPXUUzz88MPcf//9nD17lmeeeYZnn302L8e/GQjaTuvQlgJZlk3Z9K9evUooFOKOO+4wYVbJeZ0/f565uTmKi4s5efKkKePqeOGFFzhz5owpru+QnO+LL77Iz/3czxnEZ7WmWGZBURT6+/uZn5/n2LFjph3LZpG6oc/PzxuC1MrKyrSQu14x5vf7OXbsGMXFxds8840h1VDy6NGjGy6NT+127ff7N25aGltEOvf/RRp8DtBQ9v0SifaPg8Ob9fx15++jR49uqhIln0i1ZvD7/YTDYSPdFYvFuHnzJkePHqW0tHS7p7ph6ETtyJEjpqQsQqGQcZ7m5uZwuVwG8SkpKTFVAxeLxbhx4wbV1dWUlJTkJAnYbDVWrpiYmODxxx/nn//5n5mcnKSiooLjx4/z6U9/mrvvvtt4X+rWPjIyQktLy4qx7rrrLr773e8yMDDAn/7pn/LjH/8Yv99PRUUFp0+f5rHHHuPgwdvVl7/927/NyMgIP/rRj4zXXn75ZR566CH6+vqora3lc5/7HA88sLruLhqNMjw8TGNj45Z6/P2M7JC8EAKBAMePH9/0WOFwmK6uLkMTMjMzY/Q3MAs/+MEP6OjowOPZXFWMDkVR+P73v2+MmW+iE4/HjTLxI0eObEmVVC5ItWWYnZ3FarUaPUVu3LhBPB7n2LFj22bKmStUVeXixYssLi5y/PjxTZfGp5Yhz8zM5N20VNM0ozXB8ePHC4YoZwOdTI+OjhKNRnE6nVRVVVFRUVEwPaKygd4DK19ELZFIEAgEjPtP0zSjVUJZWdmmRc43b94kGAzS3Ny86aak2fbZMRMbTb2ttc1HIhGuXLnC0aNHt+T62y6y87M0FuYJlGdnZ+np6aG2tpbW1lYmJye3rH9PrtAruyoqKjh37hwul4vKysoNpyayRTAYTKtYKmSn3eWC1EAgwOTkJOfPnweS/Xzm5uZW9KkpZCQSCXp7e1EUhZMnT2KzWhGiAZBjaI7SnJr6ZTIt1au7zC7XTjXE7Ojo2JJUh5lwOp1EIhE0TaOjo8No/KiT/9R0V6FeU8PDw4yMjHD8+PG8Ncu0Wq1GS4lMrRJSDV43KnIeHx/n6tWr7N6925T1ZytJDuSmMVqrtD0aje44C55c8DOygzkC5dHRUQYHB9m/f78hss1HA0Azx00VIh85ciStQV9XV1eatsXn8206jDw7O8v58+d3ZMWSKIrY7XYCgQDV1dXs3r2b2dlZRkZG6OvrM0W4m29Eo1G6u7txOBwcO3YMSQ4iXf0eluAEaAqa5ESpOIxcdSJno8/Ucu2GhoYVpqWSJBnnaaOmpbIs09vba5oh5lZDVVUjdZtK1JaLwYeHh7l48aLhRK4b4W43NE3j6tWr3Lx5k/b29i1L3S5vlaB3UPf7/QwPD2+o4/XY2BiDg4McPnyYUCi0JfM3E4qiGA0PN5Mq09feWCzG2NhYQVvumIUdTXbM2iw3Q3ZUVWVgYICpqSna29vTQrpb2Zl5o8jUEVk34qyurk7rJNvf34+iKKt23M0GN27c4PLly1taMWMm/H4/Fy5coKGhgYaGBkO829TUZLhGb1a4m08Eg0G6urooLy9n//79iGhYR76PGJpEk1wgOhDkCNLEm2gWO0pFmynfm6lce2ZmhoGBARKJRFp34rXISzwep6urC5vNxokTJ/KqicgH9K7akUiEjo6OFanb5WLwTE7k+r23HU36dI2Xvs5tZ+owtYN66jU1ODiY1gJguchZ1xgdPXrUaLWwk2CGV1cq4vE4V65cwefzUVdXVxDrVD6xs1aMPCFXUhKPx+nu7kaWZTo7O1c80W9VZ+aNINuOyMs7yS4tLTE9PZ0WydDTXetVLF2+fJmJiQmOHz++Y4WYg4ODqxI13TW6vr4+TbirV+KkRse2I22nN6urr683fIrEhRHE8DSazQNichnQbMUIsQUs/j6U8kMgpGyoqowQuIqQCKMW14K7apVvWx3Lr6lUM86BgYFVmz4Wgk/UZqBHpBRFybokN/WakmV5RasEfTPfihSqrpHy+/20t7cXRJRJR+o1pWmakUJNbQFQXl6OpmncuHHDWINycXDfTuSD6AwNDVFSUvKOIDrwM7ID5EZKlpaW6OrqwuPxrPqkWWiRneUdkbMVIqcaAjY3N6/oKeJ2uw3ik5o/l2XZeJrdTo+oXKGH7W/cuMGxY8dW9LDIhNWiY5cuXTIiGfoT+lakYaampujr61vRrE6ILyYtIMT061az2BDiQVAScMvwU1i4gaX3fyDOXgUlBo4SlD13oRz8t2DJ3Q06k2mp3+83mj7qeowrV65QXV1Na2vrjluUE4kEXV1dSJLE8ePHc4pILXciz6Rf0Umiy+Uy9RxpmkZfXx/z8/O0t7cXbIoWVqZQ9QeP69evs7i4iCRJ3Lx5k2g0alpxx1bAbKKTSCS4cuUKHo+H+vr6HXdP5YodTXbM+pEkSdqQXcTU1BTnz5+nsbFxTe3Jdripr4ZUfY4gCJt6Ona5XOzZs4c9e/akaTKGh4eNKrSSkhJj0+ro6ChYseVq0H3MdH1FLmH71SIZeifZ1E0qHzlzvQdNW1vbih4omq04qctJRCERSnY1troQNBnVUXqbxMgxLF1/g8U/iFramCRA4Vksl/8ZnKUozfdk+OaNI5Np6c2bN7lx4waiKBKPx5mcnNxRYvBYLJZmSGpGRCqTfkUniVevXs3e2T4L6FV7wWCQ9vb2HVd1aLVaicfjhMNh2tvbEQTBaGYYi8WoqakhkUhgs9kKNlpoNtGRZZmhoSGjv847hejADic7ZkEnD+v5Tem9Pa5du8Ydd9yxoltopnFTOxObOd+NpLHy2RE5VZOhb1JjY2OMjo4iiiIej4e5ublt646aCxKJBD09PaiqysmTJ00pjV8eydA3qZmZGa5cuWL0FDGjBFk3DRwfH8/oGg+gFtejClbEm2+iKQlAAAFwlaEc7jRSWOLMAOLcNVRfkxHpoagCEhHEkVdQ9v48iOb+rrr/29zcHPv378fj8eD3+9NMS3WdT6EKK/XUm9fr5eDBg3nbTB0OB3V1ddTV1a3qbJ+LJ5Wqqpw/f55IJLIjxeBwuzw+tWrM6/XS3NzM4uIi09PTKIpCKBRCEAQkSTL+VwjIF9HRm1++k4gO/IzsAOkWDKttyLIsc/HiRebn5zl9+nRWlQj6WGb6WMHG0lhbaf2gb1KBQIDm5ma8Xq8h2o3FYkYKZz0x6nYiHA7T3d1t+MLki6ClblKpVXB6CXKqfcVG5qBHpBYWFujo6FidDKgJFJwgWBHtThA0NEVF1SyoQspvE19KRn2kdMKn2YoQYgsgx8BmbnpybGyMS5cupdkP6HYDummpThJ14a5OEgvhCV0Xg1dWVm5p6m15Z/ClpaW0SGK2RriKotDb20sikSjItv/ZYGRkhOHh4VXL4+12OxaLxSgbl2UZWZaNMuxU4rMdpEAnOna73ZTzrygKV65cweFwvCOJDuxwsmNmNRYkL4hMG0skEqG7uxuLxcKZM2ey3qjzRXayiexkK0Q2C5qmGU9Shw8fNuwxdAfyUCiUJkbNdwonF+iGrVutD5EkyegpoqqqUYKcajCpn6u1oky6EDaRSGSs+EmFsDSJkAj+/9m77vi2yrN7NL33XvG2YyfedsgihAYyyLDTlNVCCbQUCIUmARqgFNrSdAAtfB1AGWWlCS3ZBEJCyCCBQOO99x6yJMuSZW3p3u8P971ItryvVtD5/fp9RMv3Xl3d99znOc85MCWvh8mkAcdkAC3wA0cjBWeoFXRYJsDhgPYJHyM6ulHA45tWHkczDCo0DRCw19og51BHR8ekGikvL68JJFEqlaKqqgoALFycHXGHTs6huLg4RgzuCJjr7JKTky3Gtdvb2yEUCpl2l7mthNFoRGVlJWiadsmpN2DMB6irqwsFBQUz1uaYV3QoioLRaITBYIBWqwWXy2Wet0d1mqIohuiwcVNIiI5QKERSUpJT3BA4Aq53JtsA5j/08SfX8PAwKioqEBERgYyMjFmdKORCx7ZuZ7rKjnliOdkOW150yfj90NAQCgsLJ1xgzIWDiYmJzIVXLBZbtHDCw8MdNqotFotRW1uLlJQULFiwwO5/n4DL5SIoKGgCSSQZRJPdnRMPHQ8PDxQWFk6/SFH6MYEyTwDwBEwkJ83zAMeoBWgK4PBAh6SCiswBt/sy4BMKWuAFjnoI4PJBJa2xnNiaB0jrbWBgYMaLlDlJtFVo6Wwgk40l3yclJdkseX2uMB/XNplMVi0AgoKC0N/fD4FAgLy8PJdpO5uDZO0VFBTM2QeIy+VCKBRCKBQyQZvEyA+ABfFh+1pFURRUKhWrRKetrQ18Ph/JycnfWqIDuMkOADD92vEEglQh0tPT57QAcjgcmxgLTiVQHj9xZeuTmzjyGo1GLFmyZEYiRvMLr9FoZNoSZFSbTHaxYWQ4ExAhr3lFyhkwniSSxGiJRMKIv8kEXFtbG0JCQmZMyGmPQNB8T0A/CgjNxNc6BejQjG90OBwujHnbwfMKBrfvCjjaEdD+sTClrAUVw04MynizvblM7VkLLSXHytz7iOQssb1IkbHw9PR0xMTEsPrZbIPH4zE6HpqmMTo6CpFIhJaWFlAUBX9/f3R1dU2YrnR2kMnJ+RCd8SD+Y6SVZDKZYDQaodPpGNkDIT/zvVbNtKIjEonw+9//Hh9//DH6+voQHh6OnJwcPPzww1izZo3F57W1tYHL5UKn0+Hmm29GWVkZurq68OKLL2Lnzp0TPruvrw979uzByZMnodFokJaWhjfffBMFBQWTbs+FCxewe/duJhvr5z//+ZTZWI6CS5MdtkW/hEBQFIWmpib09/cjPz9/XiF3tpjIItMp42FPfQ5gqW/Jzc2d81jtZEaGRqORaUvYYgqHpmk0NTVBJBJNKuR1JpgnRptPLBExOEVRkEgkM2vh+ISBDkkFV1QFePiB5gkBjRzw8AcVtnDcH/aDKecHMC0sBoyasbDOOY6cj4fJZEJ1dTW0Wu20rbfZwNvb26r3UUVFxexDS6fBwMAA6uvrLTRGrgIOhwOhUAiJRILQ0FCkpaUxv8HOzk7G8Xom7sSOgnkorK0ND3k8Hng8Hjw8PCyqPjqdjrlpFggEsz5OhOiQitJk6OzsxKpVqxAYGIg//OEPyMrKgsFgwOnTp/Hwww+jrq6O+by2tjZwOBykpKSgvLwcSUlJuPnmm7Fr1y6rnz08PIwVK1bg+uuvx8mTJxEeHo62trYpQ3Y7Ojpw00034d5778W+ffvwxRdfYMeOHQgLC8O2bdtmdQxsDZcOAgXAmjnU559/jkWLFsHPzw9VVVXQ6XSshCReuHABWVlZM/JomSna29sxMjKC3Nxc5jF7E53h4WFUVVUhKioKaWlprP89IrAUi8WQSCRQqVRMWyI8PHzeY7DE0ValUiEvL8/lPIAAy9abv78/M91FkrVJC2fSY2UygCNtAmeoGRyTHrRvJOjQhaD9Iu2y/QaDARUVFeBwOMjNzbWLEHay0FJCfmZ7XvX09KClpQXZ2dkIDQ210VbbDlqtljFsHD81Zn7zIZFIoNfrbRrwOhcQL6y+vj4UFBTMmOjodDr09/cjISFh3vuhVndAo+mGUBgDgWCsWj0bkfNMiQ4AbNq0CTU1Naivr5+gdZTL5QgMDGSOCU3TSE1NnUC8EhISsHPnzgmVnccffxxffPEFLl68OON937NnD44fP46Ghgbmsfvvvx9VVVW4fPmy1fe4g0DnCA6Hw0qIGY/Hw+joKOrq6uDr64ulS5eyIs6zVWWHtMaIEHl89IMt0d/fz7T3zI3q2MR4I0ONRgOxWAyxWIzm5uZJjQxnAp1Oh8rKSnC5XCxZssQlp03IImveeiMtHOIiKxKJGNNHQhItjhVPADpiMejwzLGJK5aqNTOBVqu18KCxV8VgfGgpMcgcf6xmElpqHog51d2vs0Kj0aC0tJRpf47f1/E+UUQ/Nj7gNTQ01CFaO5qm0draiv7+fhQWFtp90MFgkKO+4REMD39DDoKCrkVmxp/B4/nNSORMiI5AIJiW6MhkMpw6dQrPPvus1X0lRKe9vR0URVklOlPh+PHjWLduHW6++WZcuHABMTEx2LFjB+69995J33P58mWsXWvptbVu3Tq8+eabMBgMTnVtdXmywxZI6yohIQGpqalOkbs13WeOFyLbY+KK9MVzc3Pn1d6bLby8vKY1MgwLC5s2N0ilUlmkrruaYI9c4Pv6+iZdZH18fODj4zPhWHV1dUEgEFgEcXK53DGRMW/648AZagWv+SNw5J1jup20m0CHZcx6H1QqFcrLyxEcHDxr0T+b4HA4zLGaKrR0fAtn/CJrr0BMNqFSqVBWVjbj8fjx+jG9Xs+0BkkblRwre3hqEUG7SCRyCNEB8D+i86XFY8PDX6K+YTdyst+0KnJWq9VMu4vIEQQCwYzat62traBpGgsXLrT6PE3T6OjogNFoRFpa2qxv1tvb2/HKK69g9+7dePLJJ/Hf//4XDz/8MDw8PPDDH/7Q6ntEItGE1m1ERASjxXSmHMRvPdkhJ4hKpUJsbCzS0tJY/XxbkR2KouwqRDaZTKirq8PIyMicHYXZgjUjQ7FYjJqaGtA0jdDQUISHh0+46JKMKFdMXQe+EfIODw9P7aFjhvHHirQl6urqZhXuyu35CoLPfgmOZniMHNEm8JtOQH/dU6CS10z6vvEgo9kxMTFISUlxqu9gstDSxsZG6PV6xqBveHiYiU9wFtuE2YBE3URHR8/5OxAKhYiKikJUVJRFa5DYJZCW8/gwTjZgHkpaUFDgkO9Are6wqOh8AxOGhy9Cre6Et3cCAOsiZ4PBwEgwTCYT9Hr9tCJn85gfa891dnZCr9fPiegAY9eXwsJC/O53vwMA5OXloa6uDq+88sqkZMfa9ky1nY6Ey5Od+bSxTCYTamtrMTw8jODgYJss4LYUKOv1egiFQpufVDqdjvExWbJkiVMZAo43UlMoFBCLxWhpaUFNTQ2Cg4MRHh4OiqLQ3Nxs09abLWE0GlFdXQ29Xj9nV2fzKZyFCxcyGUvm4a5WR7UpEwRf/QUc7TBo/9ixmAmaBmd0AIKv/gLdguWAYPoFbWhoCFVVVUhOTna60ezxsBb1QawSDAYD/Pz8IBaLpzXoczaMjIygvLycCYVlA+atQfN2l3kYJ1uTcGSoQCKRODSUVKPpnub5LobsjAeHw2FsTgQCgYXIeSpPH9JxaGhoQHFxscVzXV1d0Gq1SE9Pn3PrKCoqCpmZmRaPZWRk4NChQ5O+JzIyEiKRyOIxsVgMPp9v18r/TODyZGeuIL4kHA4Hy5YtQ1NTk1OFdk4GmqYZ3cXFixeZxXw6w7m5YnR0FBUVFYztvTNOYxCMHz8mF922tjbodDr4+PjAaDRCpVK51B25TqdDRUUFBALBzDx0ZoDxGUsajYYRopqPaoeFhSFALwJH3gXaK2SM6Ix9AGjvUHBGB8EV1047hi4SiVBXVzdpcrwzg8PhwNvbGyMjI/D09ERhYSHj6WNu0GfRGnRCyOVyVFRUIDExEQkJCTb7O+atwckm4Ui7azbn8nii48hQUi+vqa1IvLysk3maphmNDrlemwuTzT19xoucg4ODsXbtWrzyyit46KGHmGtYV1cXNBoNwsPD56WRWbFiBZqamiwea25unvLGZNmyZfjwww8tHjt9+rRTOm9/K8kO+dGHhoYyug1bhnay5bND9DlCoRBLly5lxJXmhnMkHZmNOx6pVIqamhrmLtBV7l6BbxYoYgSWn5/PiJydxchwJiD6lqCgIJtmLHl5eU0Y1RaLxSgvL4e/bgCFej24XCN4AhoczO5YER+jnJwcl5xYMhqNqKioAAAUFBRAIBDA19fXwgLAWmswJCTEaaqgMpkMlZWVSE1NRVxcnN3+rkAgsLCWmKvxI03TaGxsZIxLHZ2+7u2diKCga/+n2TFfN3gIClputapD0zRUKhX4fP6kN6bTOTm/8MILuOGGG7Bs2TL86le/QkhICJRKJdra2vD6669bTEWZQ6/Xo76+nvnvvr4+VFZWwtfXFykpKQCAXbt2Yfny5fjd736HW265Bf/973/x2muv4bXXXmM+54knnkBfXx/effddAGOTV3/729+we/du3Hvvvbh8+TLefPNNHDhwYJZH1PZw+dFzo9E4K5LS39+Puro6pKamWqS+NjY2gqKoCWW8+aKurg4CgWBeWqCZOCLrdDpIJBKIxWLIZDLmzjw8PHzaqRJr6OnpQXNzs0veiQPftH10Oh3y8vIsRhxJzIBYLIZUKmXEleHh4XYzMpwJ5HI5KisrHapvoSgKw0MS+J/4CQSKdmgEIRAIhRDw+RDqpIBfFHS3HAAEE8m1uf9Jbm6uS04s6fV6lJeXQygUIicnZ8rKpnkelUQiwejoqFPEokilUlRXV2PhwoWIjo52yDZYg7nx4/DwMHMDEhoaisDAQOZ8p2kaDQ0NkMlkKCgoYIXosDF6bjAoUN+w2+o0lkBg6dllTnTm8veIyHlkZAQVFRX45z//iUuXLkEikSAsLAyFhYXYtWsXVq9ebfX9nZ2dSExMnPD4ddddh/PnzzP/PnHiBJ544gm0tLQgMTGRITEE27dvR2dnp8V7Lly4gF27djGmgnv27JnSVNBRo+ffGrJDRG3kwjv+DrOlpQVarRZZWVmsbl9jYyNomkZGxuynVoC5OSITJTxZzMkETnh4+LTTSuZGe666QJlHJ2RnZ09ZKh/vJWIwGGxqZDhTEEdeR8dXEIwJlJ8C1DKYKIAyGaDneKIr9W7wMm6asJiTO3GJRIL8/HyHCtrnCjIe7+vri8WLF8+aBJsn2w8PD8PT09PuoaVEuL9o0SJERtrHP2kuMA/DlUqlAMC0uqRSKRQKBQoLC1lbHNn12emERtMFL6/4aSs6bGw/RVHo7e2FUqkEh8OBXq+Hn58f05Z2Bv+jqeAmO3PETMiOwWBAdXU11Go18vPzrd5hdXR0QKFQWBj1sYGWlhbodDosXrx41u8lFR2TyTTnsXKKophpJYlEMuW0ktFoRE1NDTQaDfLy8hxeKp4LlEolKioqZhWdQGB+Zy4Wiy2MDO2VrwSMxZQ0Nzdj0aJFTuXIyxlqBa/pQ3CHO0D7x0KdcANECINEIoFMJmPuzENCQtDd3Q21Wu2y55FarUZZWRmCg4ORmZk576qa0Whk2l0SiQQALLQrtiDVRCeVlZXlVDEo08E856y3txdGoxEBAQGIiIhAaGgoKxUyNsnOVCAaHZKwzgb6+/shk8mQnp4OT09PaLVaKBQKKBQKKJVKZGdnO51exhxusjNHkKySyUA0D15eXsjJyZn0JOju7oZEIpkyA2QuaG9vh1KpRE5OzqzeZwtHZPNpJbFYDJ1Oh5CQEMZsrq6uDkKh0Ol/LJOBaIzi4+ORmJg472NGRLtisRhyuXxycz6WQNo+3d3dyM3NRVBQEKufb0uQO/PBwUGIxWIAYEI67eG7wibIaHZkZKTN3MHJYk4cr9km1UTH56rOzjRNM1YXixYtYiYHZTIZvLy8LNpdc6mQ2YPs2ILoDAwMQCqVIj093ep5YjKZnP635nZQtgGkUimqqqoY/5ypLlq2EijPZRqL6HPYdkS2Nq0kFovR0dHBBNARPxZXIzu9vb1oampiVWM0XrRLFidizkem4OZ6wTUHSY6XyWQO9zGaC/h8PgIDA9HR0YGgoCDEx8djaGiI8V0hU4OhoaE2mRpkC2R4gS3CbA0zCS0lrdS5jGoTd+3c3FxWY2rsBYqiUFdXB6VSiYKCAnh4eCAgIABxcXEWFbKamhpQFDVjryh7whZEZ3BwEFKpFGlpaZMSYmcnOo7EVUl2aJpGV1cXWlpakJmZOaMUYh6PN2WFaK6wlqY+GUj0A3m9LR2RiSOqSqWCTqdDYmIiBAIBpFIpWlpamDiG8PBwp/YRMXd1zsvLs9nFXSAQTDAyJBdc0hokLZzZjoaPD8N09p67NWg0GiZjiUw4kmBJYgHQ19eHhoYG+Pv7W4h2neXcIj5A9tZJsRla2tnZiY6ODpeNsKAoCrW1tVCpVCgsLJwwzcbn85nrEk3TTMWnq6sLdXV1jCCctLsccW4RosPlcln7LYvFYgwODiItLc0lc/ycAS7fxqIoCgaDweLfdXV1kEqlyMvLm/EPnjilXnvttaxuX39/P7q7u7F06dIpXzcXIfJ8QBw3Ozo6LPKVADC2+WKxGENDQ4ywMjw8fN6mYGyCfNdyuRx5eXkOqYaYtyTEYjG0Wq1FCOd0VQy9Xo+KigrweLwp26zODNL2iYiImDZ6QKfTMeeWTCabVdSHLUGEvBkZGU4zsUSciUnVR6vVWrS7zBdS4gTf3d2N/Px8+Pv7O3DL5waKolBTUwO1Wo2CgoJZj+1rtVrmWJmfW6GhoRP8j2zVxjInOmxp1UgeWWpqqstVfK3BrdmZI8zJDjFfoygK+fn5szqQJMV7stG9uWJwcBBtbW1Yvnz5pK9hQ4g8G5CWydDQEPLy8qbM9jGZTBZj2hwOxynGtA0GAyorK0FRFHJzc52mNUJagxKJBCMjI4z3kbXRY7VaPeZj4+8/p2kfZwCJ4JhL24ecW+NFu3OtkM0VJNjW2YW8pEImkUigUCgsgjgHBwcxMDCA/Px8l8zqIkRHo9EgPz9/3v5E5tVXqVQKo9Fo0e6iaZp1smMLoiOVStHf33/VEB3ATXbmDEJ2SOZOUFAQFi9ePOve5cjICK5cuYI1a2ae8zMTSKVSNDQ0TFoxsoUQeSro9XpUV1fDaDQiNzd3VicbudMkizm5gBAthr0WJ7VajYqKCvj4+Ng1MXu2IN5H44WVYWFhAIDKykpER0ezGjxrT4jFYtTW1iItLQ2xsbHgjPSCoxSB9gwAHZzyjdvyDGBNtGteIbPVRdHc8NDZ7O2nAgniNJ+yjIiIQFRUlEVoqSuAoiimjUtMG9mE+ZSlVCqFUqlkNFOJiYmstIVsQXSGhobQ29uL1NRUlySwk8EtUJ4HBgYGUFtbi+Tk5DmLCm3poDzZ59pKiDwZVCoVKisr4ePjg7y8vFlfEMdn4CiVSojFYrS3t6O2ttbm0RXAWJBkZWXljFomjoaHhwdiY2MRGxtr4SNSXl4Ok8mEgIAABAUFgaIol1qcAKCvrw+NjY1YvHgxIoL9wP/qb+B2fwGOfhTge4KKzIKh6AHAJ2xGnzdZ1IdIJEJTUxOjIQsLC2NlEo60fbq6ulxS3yIUChEZGYnh4WEIhUKkpqZCoVBYhJaSKoazVD2tgejV9Hq9TYgOMHZu+fv7w9/fH8nJydDpdBgcHIRWq4VGowFFURaxDLOFLYiOTCZDb28vUlJSriqi40i4PNmRy+Woq6tDTk7OvErQJNaBEA+2YI3s2FOITCCTyVBdXc2aG6/5BSQlJYVZnMjIKxEKshVdAXxTSXAWo73ZgM/nIyIiAkajESKRCImJiTAajWhsbITBYLCokDmzboeI/zs6OhhBOL/iHfBaToL2CQPtEw4Y1OB2X4aApmFY/fSsKjwE5vlKRENGQkuJSeZcs6homkZLSwsGBgZQWFjokosJRVGor6+HQqHAkiVL4OnpiaioKCa0VCqVThCEh4aG2sQyYa4wmUyoqqqCwWBAfn6+3c57Dw8PREREoL+/Hz4+PuDz+TAajdBqtRPyqGZyrDQaDatEZ3h4GD09PUhOTnZJ7ZWzwuXJTlBQEFauXDnvchhh9EQ3wxbGk53xQmRr0Q9sg9yF2zLx23xxMo+uaG1tnXd0BfBNu2G8mNpVML6SQKbGzBO1yUSJI4wMZwJzklBQUDB2IdYpwe04B3gGAl7/m4Tz8APtHwvuYA04Q82gQ9Pn9XeFQqHFJNzw8DBDfGc7ekzTNOrr65kRf1ecbCH6FjKxZF654XA48PPzg5+fHxITExlBuLOFlhKiYzQa7Up0rGG6PCqBQAA+n2/1WKnVagBg7Xcql8vR3d2NpKQkBAQETP8GN2YM11NEWgEbfT/SRmC7lUUqRubVHIqiwOFwbF7RIYtTc3Mz8vLybEZ0xoO0b/Lz87F69WokJiZCrVajtLQUly5dQmNjI2Qy2YwCUkl8RXt7OwoKClyS6BBBeG9vLwoLCy3G48nilJycjKVLl2LFihUICxtzJf7iiy/w1Vdfoa2tDUqlEo6U15HJN7FYjKKiIuaOk6NTgGNQgxaOc7UV+gBGLThaOavbwePxEBoaiszMTKxatQr5+fnw9vZGZ2cnLly4gLKyMnR3dzMBsOP3oaamBgqFwmWJDiEJGo1mAtGxBg8PD8TExCA3NxerV6/GwoULme/y/PnzqK6uRn9/P/R6vZ32YGwfKisrYTKZHE50xoPL5UIoFMLb2xu+vr4QCoUwmUxQqVQYHR2FVquF0WhkWlcAWDuPFAoFurq6kJiYOGVbVSQS4aGHHkJSUhI8PDwQFxeHzZs347PPPpv0PXV1ddi2bRsSEhLA4XDw0ksvTXgNeW78/x588MEpt/vChQsoKCiAp6cnkpKS8Oqrr850l+0Kl6/ssGm4NxcDwOlASJTRaASHw7GbPsdkMqG2thZKpRJLlixxWAghn8+3SD0m0RXm/jTWoivIPpA72CVLlrjs4lRdXQ2NRsO0G6bCeCNDMqZNjAxnmnFmi30gPkDmCyztFQLaKwgcjRy00GxaRKsALfQF7Wu7PCYOh8PkAaWkpDCO1+bmfOZ+PkQbYs2/xRVgThLmom/h8XjM8TAX7XZ3d6O+vt4uoaUmkwkVFRWgaRp5eXl2G2qYCzgcDgQCAXOcTSYTU/GhaRocDgdCoZD57/lAqVSis7MT8fHxUzqnd3Z2YsWKFQgMDMRzzz2H7OxsGAwGnDp1Cg8++CAaGxutvk+tViMpKQk333wzdu3aZfU1V65csVj/amtrceONN+Lmm2+edHs6Ojpw00034d5778W+ffvwxRdfYMeOHQgLC8O2bdtmuPf2gctPYwFjUy9s4LPPPrO4a2UDFEXh9OnTWLVqFVMKtTXR0el0qKysBJfLRU5OjlNe2K1FV5Cx47CwMFAUxexDbm6uU939zRR6vR6VlZXgcDjz3gfzUVqJRAKKophjZcsxbYPBgIqKiin3gVd/GPyKdwC+J2jPQMCgAkczDFPyDTAu2zknzQ4b203aN1KpFBRFQSAQYOHChQgNDXU5QbjRaLT4Htj+vkloqVQqhUwmY7y15hPJMB5GoxGVlZUAYJN9mA3m47OjVqtB0zQEAgGMRiP0ehkoahQeHkHw9Jz9uaVUKtHe3o4FCxYgJCRkyvXhpptuQnV1NZqamiYQUrlcPiOhfUJCAnbu3ImdO3dO+bqdO3fixIkTaGlpmXSb9uzZg+PHj6OhoYF57P7770dVVRUuX75s9T3uaax5gMPhsFLiZ3sii7SuBAIBM0HEpmDXGpRKJSorKxEUFITMzEyn9W6ZLLqC3GVyOBz4+Phg0aJFLkl0NBqNRWL2fBfX8XflZEy7ra2NmYSbqZHhTEFSv729vacc8TctLB7bxuaT4GhloPneMGVshTH7docQHWDM8ToqKgohISEoKysDl8uFv78/mpubUVdXZ6HzccabAXMYDAaUl5dDIBAgJyfHJkTN09MTcXFxk0YymPsfzeX3SMgauXlxNbJJQFpXPj4+MJm0kMlOQaPpZp4XCGLg7389hEKfGU13jY6Oor29HXFxcdMSHZlMhk8++QR79+61Wnljc6JQr9dj37592L1795TbdPnyZaxdu9bisXXr1uHNN9+EwWBwqmv3VUF22AJR5bMBYhRIURSWLl3KtCOIYJdYnrM5HUEuTgkJCTbL9bEFSHSFr68vgoKCUFFRgYCAANA0jS+//NJloisIRkZGUFFRYbPx+MnGtMkkHJm+IcdrLiABusHBwdOnx3N5MGV+F6bU9eCopKA9/QG+F8Bz7IWOEE4/Pz/GtJGmaUYQPr59Y+sbkblAr9ejvLwcnp6eyM7OtsvNy/hIBkKsOzo6UFtbywjoQ0NDZ3S8jEYjysvLwePxrgqiQ/ZZIjkJjabH4jUGQz9Uqs/h4XETdDodNBoNeDweI3I2vxaoVCq0t7cjNjYWoaGh014nWltbQdM0Fi5cyPKeTcTRo0chl8uxffv2KV8nEokQERFh8RiZOpVKpazlFLIBN9kxA1uVnfFCZE9PT8ZvxVyH0dnZCQ8PD+bCMp8oBjKtlJmZichI2+kkbImBgQHU19dbTI2ZR1d0dHQ4bXQFAclXSkpKQnx8vF22z9okHJm+8fT0ZPxpZnq8iEHnrG0KBN7gyDsg/O8r4EjqAYE3TJnbYFiyY0ywbEcQshYSEoKMjAxmH8ynlZKTk5n2jUQiQWtrK7y9vZkKmaPPL51Oh7KyMqY66Igq7XhiPV4XNd3xIm1QPp9vs6qUPTCe6BgMwxYVnW9AQ6vtBperho9PkMV0l1wuh0QigZ+fH7y8vNDf34/o6GiEhYXN6Dwzn+C1Nd58801s2LBhRtEp47fHnts5G1wVZMeZ2ljTOSKT8npUVJRFFAMp8RLiM9OxUIqi0NzcjMHBQZc0RwMsc7pycnIQGhrKPDd+7Hj88XKG6AoCEjvAZvL6bDGZkaH58QoLC5vUZZeQteTkZMTHx8/qb3M7zsHjo4cBoxY03xPQKsAvfR0cSQP0JW8AHPt8PySrKzo6elqyNr59Q44X0VrNJoSTTZBgVdKOdpaFY7yAfmhoCFKplNETmZ9fNE2jvLwcQqEQ2dnZLkt0NBoNaJq2qGIZDIop32MwKCAQBDHTXUKhEB4eHuBwOJDL5RgaGgKHw4FarYZcLoe/v/+0x4c4rTc0NKCkpISNXbOKrq4unDlzBocPH572tZGRkRCJRBaPicVi8Pl8p3MkvyrIDluYL9mZbfQDj8djyA1FURP8Q8hCPtmF1mg0MlMyS5YscSpPlpmCoig0NjZCKpWiqKhoSoO38ceLRFc0NDQ4LLoC+IasdXZ2Ijc312l+5MTIMCIigjleJPCWGBmSxUkgEEAkEqGurm5uZI2mIfj672NExzOI0erQRh14PZfB7fkK1ILJ8+HYglwuR0VFBdPKnQ0mO17Nzc3Q6XR2cyVWq9UoKytDaGgoFi5c6DREZzwEAoHFpCVpd7W0tDDtGw8PD6Snp7s00aEoCt7e3hbfg0AwtQeOted5PB58fX0xMDCAqKgo+Pn5QaFQoK+vD+3t7fDz80N8fPyk51ZwcDDWrVuHv//973j44YetCpQ1Gg2Gh4cZjyBfX1/ExsZaCIGNRiO6u7tRWlrKPObj44OMjAwAwFtvvYWQkBBERERYvCYoKAjJyckWf3PZsmX48MMPLR47ffo0CgsLnUqvA1wl01gGg2FGni3TobKyEgEBAbO+SBIhMlvRD5NNKpk77Go0GlRWVsLDwwNZWVlOd2LNBISs6XQ65OXlzVmZT8ZoyfFSq9UWC7ktFyaaptHY2AixWOwyIYzmuhWJRILR0VF4eXlBo9EgIyMDMTExs/9QvQpery0DDRoQmOk4aBocnQKG5btgLLqfvZ2wAlKVSk1NRVxcHGufS9O0RQgnCXg1H9Nmi5CMjo6irKwMkZGRSEtLc1qiMxX0ej2zSAoEAovQ0rCwsDkbi7KJmUxjTUZ0CESiI//T7JgvoRx4ecUhMnLrhNdrtVq0tLQgLCwM0dHRFp+p1WqhUCimnRTs6OjA8uXLERwcjN/85jfIzs6G0WjEp59+ildeeQXHjh1DcHAwfHx8QNM0+vr6oNFokJqaiqamJgBjAuJNmzbh/vvvh6+vL1P95PP5oCgKiYmJWLduHZ588kmLawGHw8Evf/lL9PX14d1332W2Z/Hixbjvvvtw77334vLly7j//vtx4MCBSUfP3UGg84DRaGRFa1NbWwsPDw+kpqbO+D3mJAdg3xHZfGESi8VQqVTw8/ODSqVCeHi4U09cTQWtVouKigoIhULk5OSwWokhC5NYLMbIyIjNBKjEy0ilUiEvL88lK2vEtLGvrw++vr5QKpWMgH5WCxNlhOdrywC9CvAwI3w0BY5uBPrrfwVT9u0224/BwUHU1tbapYU4PuCV6O6IbmWuv0elUomysjLExsYiOTnZ4YRgLtDr9SgrK2Mm+LhcLhNaKpFIMDQ0xBhDTtVOtTWmIzvTER0AMJm0/xMpf6Pd8fJagLCwDeDxLD9Tp9OhpaUFISEhiImJmdd3OzAwgL179+LEiRMYGBhAWFgYCgoKsGvXLqxevdritQaDAVVVVfD09ERWVtaEz7ruuutw/vx55t+nT5/GunXrcPLkSWRmZk6I5dm+fTs6Ozst3nPhwgXs2rULdXV1iI6Oxp49e3D//ZPf2LjJzjzAFtlpaGgAh8OZsdp9fPSDPUhHd3c3mpub4enpCa1Wi4CAAKa14yqLrVKpREVFBSMeteVxM4+ukMlkrERXAGMXkcrKSsYczRUra6QqJZFIkJ+fD19f3wn+NLPJoRKcfxb8yvfG3JR5Qobo0EJfaH/4yYxDQWeLvr4+NDU1ISsri0mUtxeIjoyQHwAWOp+ZkniFQoHy8vI5td+cBdaIzniQdj05Xo4KLZ2K7MyE6JjDYBj+n0YnAALBRENAvV6P5uZmBAUFIS4uzq4kVqvVora2FosWLWLWh46ODsjlcnA4HPB4PPj5+SEmJsbiGtbU1MS4kPP5fAQEBCA6OpoVYuomO/MAW2SnubkZBoMBixYtmva1s9XnzBckW6mzs5O5qOt0OqYVIZPJXGJEWyqVoqamBvHx8XYfjyfjkGKx2GIhn60jsUajQUVFxbT+M84M83ylyapS5o7XxMjQ3PF6wkKuVUD44QPg9ZdjrLRPgxb6wnDjH2BKWTvh89lAV1cX2tvbkZOTYxHD4QiYj2lLJBKo1WoL/6PJLuzDw8OorKxkJvhcEXOZHJusPUjIoi1DSycjO7MlOtNBr9ejpaUFAQEBWLBggV2vdzRNo7W1FSaTyeIGXiaTgcvlwsPDAzqdDn19fQBgceMpkUjg4eHBSCZ6e3vh6emJtLS0eW+Xm+zMAyaTiRV/nLa2NqhUKmRnZ0/5OvOKjj2CPEnCsUwmQ15enlVdiPlIu1QqZUaOw8PD4e/v7xTEhwSSOnJaiWD8Qk7TtIUj8WQEhkz6hIeHO7V4dCoYjUYmhDEvL29Gpno0TWNkZIQ5XmQhJ+0b5o6cMoHbdRFccS3g4Q9jynrAl/08M5qm0d7ejp6eHuTl5TllaKL5Qq5QKODn58ecY2QhJzqjtLQ0u2XXsQ1CdPz8/LBo0aI5V2rNQ0uHhoZsGlpqjexotVqYTCbWiI7BYEBLSwsjPLb3taKrqwsKhQILFy6c8jeu1+tRU1ODpKSkSaMqVCoVGhoakJGRMe8oETfZmQfYIjudnZ0YHh5GXl6e1efZFiLPBHq9HlVVVaAoCrm5uTMq85qPaEskEmaKyVFJxzRNo62tDT09PU5xBz4e00VXkPLu0NAQqqurkZCQwITmuRp0Oh2jlcrOzp6zVmr8Qm4rwa41EJ0REYX7+vpO/yYHg/hFkYVcIBDA19cXMpkMCxcunJso3Amg1WpRVlaGgIAALFq0iLXvncSjkGNGpi3Zcr0eT3bYJjpGoxHNzc3w9fV1yLWiu7sbcrkc6enpM1ozampqEBoaOulNKLERSExMnPf120125gG2yE5vby8GBgZQVFQ04TlbC5GtQaVSoaKignGAnUu7xHykXSwWz7iCwRZIwrJcLkdeXp7TL0yktE6O1+joKIKCguDh4QGRSITMzMwZGW05I4h3C1mY2CK95I6c6KJsafxIqpxyuRwFBQWs6dQMxrHLoIBv+0XJZDKhvb0dnZ2dDNmcbxyDI0CITmBgoE29gMxDS8n0oHlo6VwIijnZAcA60WlpaYG3t7fdW/U0TaOnpwfDw8NIT0+fEZkgld74+HgLjzNzaDQa1NXVIT09fd4Tp26yMw9QFAWDwTDvzxkYGEBXVxeWLl1q8bgjhMgymQxVVVWIjY2dnYvtFBhfwSDiQPORdjZBRLyzqUo5GzQaDZqamhjx6fgoBlep7pD2m60iLAjMq4pSqZQx5iPGj/Mh1xRFMQny+fn5rJxPCrUJDf1aKNRjNzGB3lxkRHvC39t2NwHEKTw7OxuhoaEYGRlhFnKVSsXEMYSFhTnt0IFWq0VpaalDTA+1Wi1T8SHkmpDFmWrvCNmJiooCj8dj7bdsMpnQ0tICT09PJCYm2r2K3tXVBZlMhpSUFAsiwePxwOVyYTKZ0N/fj6CgIAgEAuj1evT29kKv1zM31FqtFjKZDAEBAeDz+dBqtejp6QGXy7VwI58r3GRnHmCL7IjFYrS0tGDFihXMY/YWIgPfaFtsWd62NtJONBjh4eHzLhNfDSJemqbR3NwMkUjE+ACRCsbQ0NCcohgcASKAtbco3NyYTyKRWLQHZ9uKMNcZ5efns0LMVToKXzarQI27AvK4wPJUH3h7sL9QkcmxnJwcq+aT5nEMw8PDrE0PsglSISS5aY7cJvNpOJJuP5MqGVnAo6OjERQUxBrRaW1thVAoRFJSkkMsQcxNAM2RkJCA0NBQUBSF1tZWqNVqmEwmCAQCZhqL/B71ej3a29uZ1p5QKGSmsdiwCHGTnXmALbIzNDSEuro6rFq1CoBjJq5aWlrQ19dnd22LWq1miA/xppnrSLtCoWBS3m1ZRbAlTCYT6urqoFQqkZeXN8GfZ7wuytmiKwiII7ejBbCEXBMbgNHRUQQGBjLHbKpzjOQr8Xg8Vj2Z6vu06B0yYPwFkAMgLkSAjBh2L8Qkvy4vL29SIag5zG0AiD+NeRyDI84xjUaD0tJSp3R3JiJ6a1Uy89BSYrnA4XCQlpbGSvWMEB0+n4+UlBSn+f07I9xkZx6gaRp6vX7en0Os5q+//npGn2MvokMM6sjiOl/F+3xAwhHFYjGGh4dnNdJOFteUlJQJhlSuAnMPndzc3GkrEObRFWKxGCaTyaKCYc/oCnOQKsKiRYsmJBM7GuPPsckqGDqdDuXl5fDy8mK9QvhlswpKrXXndX8vLpalsvcbJNlv+fn5c5ocG+9PYy3uw9YgMRZhYWEucRMzvkpGQks1Gg2USiWioqJYWXBJtYTL5SI1NdVNdKaBm+zMA2yRndHRUVy+fBlr1qxhfHvsIUTWarWorKxk7lzn20JiEwaDgVmUzFs31kbayZ3r4sWLER7O/rixPaDVapnFdS7hheZ3l/aOrjDfhq6uLiZY1dmm38ZjMiPDgIAAtLa2MroQtheR0nY1hkat+3OF+fGQnzh/t23zEfmCggJW4kSsxX2QKhkR7LINQnTCw8NdMsaCeGy1t7dDpVLB09MTERERSEpKmteNJUVRaGtrA4fDQUpKiku26+0NN9mZB9giO2q1Gp9//jlWrVoFgUBgF4ZO3ISDg4OdPvrBZDJZePnw+XzmAiuRSBhtizN6nswE5LsgJXo2vgt7RVcQkFbowMAA8vLy4O/vz/rfsCWI/1F/fz8GBwfB4XAQERFhkyrZoMKAyi6t1efy4r0QHjC/v2X+XRQUFNhsEpFUyYhgl1Qw2NKSqVQqlJWVISIiwiWJDvCNwd7AwADy8/Oh0Wggl8sRExMDPp8PHo8HgUAAPp8/4/0jlho0TSM1NdVNdGYIR5Ed511Z7QyapiEQCBAQEICLFy+isrISvb290Ol0NvubEokEV65cQVxcHKujwLYCj8dDREQEsrKycN111yEjIwMmkwkVFRXo6elBUFAQ9Ho9K27W9oZMJkNpaSliY2NZjbDw8fFBQkIClixZgmuvvRZRUVGQyWT48ssvcfnyZbS2tmJkZARs3HOQMX+xWIyioiL7ER29Cry6gxCcfhyCs78Ct/0sQM8tmJfL5UIoFEImkyEhIQGFhYXw9PREe3s7zp8/j/LyctZ+l+H+fCSETWz/JIULEeY/v4WLeAENDg6isLDQppYLnp6eiIuLQ35+PlavXo3k5GTGT+nzzz9HXV0dJBLJnH6XKpUKpaWliIqKclmiA4wZxvb39zOk09/fH3w+H15eXvDx8QGfz4fBYMDo6ChUKhV0Ot2Ux4tU7CiKsntFRyQS4aGHHkJSUhI8PDwQFxeHzZs347PPPpv0PXV1ddi2bRvj+fPSSy9NeI3RaMRTTz2FxMREeHl5ISkpCb/5zW+mDdm+cOECCgoK4OnpiaSkJLz66qvz3UWbwDFiApYx3x+g+Wh5UVERtFotxGIx+vv70djYiICAAERERCA8PJwVJkrTNLq7u9HW1uaUeoqZgMvlwt/fH21tbfD390diYiJkMhkaGxthMBgsUtodpVmZKUQiEerq6mxu7ubh4YHY2FjExsbCYDAwAufS0lIIBAJmsms20RUEJpMJ1dXV0Gq1KCoqst+Yv1YB4cc/A1dUBfyPsPGaTsCUUQLDdU8CnNntB5kcS0xMZDxQAgMDkZqaylTJBgYG0NjYCD8/P+aYzWV0mMPhID3KE7FBQoiVRnAAhPnz4TPPKSyaplFfX4/h4WEUFhbadXycz+cjIiICERERFtNwTU1N0Ol0Fi3V6drlJIE9OjqaNfsLR6CtrQ19fX0oKCiw2rIiBFsoFIKmaRiNRhiNRqjVaiYNHACEQiG4XC4T3WM0GpGWlmbX61tnZydWrFiBwMBAPPfcc8jOzobBYMCpU6fw4IMPorGx0er71Go1kpKScPPNN2PXrl1WX/PHP/4Rr776Kt555x0sWrQIpaWluPvuuxEQEICf/exnVt/T0dGBm266Cffeey/27duHL774Ajt27EBYWNikqeeOwlXRxgLGxuXmsivTCZHHCyn9/PwY4jOXNgRFUYz7a25ursu2fIjh4XiDOmIARsS6RLNCFiVn0iMBY74UbW1tDgmRJKAoyiJMcrbGj2RaicPhIDc3166mdPzS18H/78ugvUPHwj8BQKcEx6iF/qaXQC1YPuPPkkgkqKmpmdHkmF6vtwh4taWR4WxAqmsjIyPM3a4zYLIcqslcrwnRiYmJcdkEdgBob29Hd3f3hOradKnnBMSwdmBgAHK5nDlOBoMB6enpEAgEaFNr0anRI9HLA0netr3JuOmmm1BdXY2mpqYJxE0ulyMwMHDaz0hISMDOnTuxc+dOi8c3bdqEiIgIvPnmm8xj27Ztg7e3N9577z2rn7Vnzx4cP34cDQ0NzGP3338/qqqqcPnyZavvcVQby7lvuW0IEv1ASpWTTVyREnFcXJzFBba1tRU+Pj4IDw9HRETEjO4sDQYDqqurodfrsWTJEqc1DJsO5O7bmuEhh8OBv78//P39kZKSwrgR9/b2oqGhAYGBgYzA2ZELAdFTkNK2I0knGVsPCwuzMH5sbm6eNLqCgAiqHeVnxGs/A3B43xAdAPDwA3Qj4PZcnjHZIdW1RYsWITIyctrXC4VCxMTEICYmxsIGoLKyEgAsbADsdUxIuKparUZhYaFTmWhyOBz4+vrC19cXiYmJ0Ol0DPFpb29nyGJYWBh4PB7Ky8sRFxeH5ORkR2/6nNHR0YHu7u556aV4PB54PB4SEhKgUqkwMDDAeNSUN7fgDyrgsuobvejqYD+8mhmPQAH7S6tMJsMnn3yCvXv3Wq1QzYToTIWVK1fi1VdfRXNzM9LS0lBVVYVLly5ZbXkRXL58GWvXWob8rlu3Dm+++SYMBoNTuYF/K8nOeEfkmU5cmV9gzYM3Ozs7pw3eJCZ7np6eKCoqcvrWzmQg7q/p6ekz8m3x8fFBYmIiEhMTmfagRCJBc3Mz04YgI+32Arn7VigUWLJkiU2EwnMFh8NBYGCgRetGLBaju7sb9fX1jG9IeHj42AW3vJwxd3OI5ouigEl+O5wZ6nZ6e3vR3NyMnJycSe3qpwLJfgsPDwdFUQxZNG/dkJaqrSqLJpMJVVVVMBgMKCwsdKqLvDWYt1TNjfkqKythNBoZYmQ0Gl3yWtXZ2Ymuri7WJuAAQCqVwmAwMBlgt1W24muVpXbsokyJ++u78H7O7EniwMAAhoeHodVqweVy4evri9jYWOamsLW1FTRNg8/nW5gH+vj4ICMjg/k3RVHo7e2FTCYDRVFMEOl05/6ePXuY4FAejweTyYS9e/fi9ttvn/Q9IpFoggwjIiKCmX5zdOCzOVzvLJ4EHA5nRm0stoI8BQIBoqKiEBUVZTGlVF5eDj6fz1x8AwMDGZO9yMhIpKWlOb0Q2Rpomma8Qua6KHl6emLBggVYsGABE4w4ODiI9vZ2eHl5McfMlk6xpLpmNBqxZMkSp2urmcP8bjwpKYnxDSELOYfDQUBAABYsWOCwNoMpcTX4pa8DlBHg/u9yYlADXD5MsUumfT85pyYz2lPrKGj0FDyF3BlpabhcLoKCghAUFIS0tDTGyJCQRVuMaBuNRsaXiS13Z3uCkEVPT0+IxWLExMRAIBCgtbUVtbW1CA4OZqbhnKUtNxWI7QKbRKe7uxsqlQrp6ekQCoVoU2vxxehEkbwJwHmZEu1q3axbWkqlkrnxo2kafX19aG5uxqJFi8Dj8Zj1zcfHBzk5Ocz7xv/2e3p6IJfLkZSUBD6fj56eHrS0tEwb6/Hvf/8b+/btw/79+7Fo0SJUVlZi586diI6Oxl133TXp+8Z/pnkRwZlw1ZCdmcBWjshkSomIAklJvaqqihG8xcbGuizRoSgKjY2NkEqlKCoqYuUCIhQKER0djejoaBiNRgwNDWFwcNBCrEvIIlvfk1arRUVFBTw8PFBQUOByd6xeXl5YsGABfHx8oFAoEBYWBoqi8N///tdh0RXGxbeC1/k5OENNY+0seqzSY0q6AdSCFRavpSgaMpUJRopGgBcXfd0d6O3tRUFBwYTJMYOJRn2vFhKlETQ9VjwK9eVjUaznjMM6ORwO/Pz84Ofnh6SkJAv9XUtLCytRDMSAksvlIjc31+XOKYKRkRGUlZVZCMMnE4UTsujr6+t0C1p3dzfa29uRn5/P2jRib28vlEolQ3QAoFMztdVJh2b2ZCctLc3i3wkJCaiqqoJarYafnx9SU1PB4XDQ3t4+KaEmFZXExERm/xMTE1FdXc1YX0yGxx57DI8//jhuu+02AEBWVha6urrw+9//flKyExkZCZFIZPGYWCwGn8+3GofiSLjmL3MOsJcjMtFfhIaGoq2tDV1dXQgNDYVYLMbg4CBzcQ0JCXEJ4mM0GlFdXQ2dToclS5bY5M5u/AQJKalXVVUBALOIz+eYjY6OMn5GDmv5sACibcnMzGRKxOaalYqKCnC5XOaY2TxWwCcUus0vg99wFNyeywDfE6akNTClb/ym0gNANmpETY8WeiM9Fs9AU+BqgaWTjGU39GkhHjGCywG4HIAGIFEaUdurRV7C3LRu5vo7cyPD0tJSphobFhaGoKCgGR0zg8GA8vJyCAQC5OTkuKzPikKhQHl5uQXRIfDx8WHsE0g1ViKRoKOjA0KhkLmezWWCkG309PSgra1tzi7V1tDX1weFQoG0tDQLDVaC19QV4USv+eu1iJ6UEOjg4GCsWrUK7733HrZt2wZfX18m10ogEEAulzPTYuZETygUwsvLi0mLnwxqtXrCd8jj8aYcPV+2bBk+/PBDi8dOnz7tlK3cq57szFSIzCZMJhPq6+shl8txzTXXwNfXlxGeDg4OMuPZ5EIRGhrqlBdKUgkRCoV20xmZi3UzMjKYGAbzkfaIiAiEhITMeHuIoJoILp3tbnSmIA7V49uI4zUr5JjV19fbJ7rCOwTGgh8BBT+y+rTOQKGySwsjRYMLgKJNAA1QXhGQaYUYz3U0egrikbFRcO7/vqux/0tjaNQIlY6a93i4eRuaGBlKJBLU1dXN6Jjp9XqUlZUxwnBHL/RzBSE6SUlJiI+Pn/K15tVYk8nEHLOampoZB3DaCr29vUzuGFtEp7+/H8PDw0hPT59wk5fs7YnVwX64KFPC3I2HB+DaYL95T2XRNI2enh74+vpaDLK8+OKL2LBhA370ox/h8ccfR2hoKKqrq9HR0YFXX30Vly5dshiXN/+8qqoqSCQS6PV69PX1obKyEr6+vkhJSQEAbN68GXv37sWCBQuwaNEiVFRU4M9//jPuuece5nOeeOIJ9PX14d133wUwNnn1t7/9Dbt378a9996Ly5cv480338SBAwfmtf+2wFUzem40GieYQM1ViDwf6PV6VFVVgaIo5ObmWp3IMB/PHhwchFarRUhICCIiIhAaGuoUjJi4CYeEhDhFJWT8SLtGo0FwcDBzzCbT3gwODqKurs7hQZjzgXnkQG5u7oynLpwhugIAOiV6tIh04ACgKBNoAHweDxQNeAu5WJFuKU6XjRpR1qEBj2PZ96dpGiYayEvwQqifbYi3tWNGNCthYWHw9PSEVqtFWVkZ/P39XcIMdDKQLMDk5OR55dhNFcAZFhZm86lTInDPz8+f8W9jutHzgYEBSKVSpKenT7r9coMR99d34bxMyTzG1jRWV1cXIxYef20bGBjA3r17ceLECQwMDCAwMBAFBQX4+c9/jqysLHR2dqKgoMDiPWfPnsWaNWsm/J3rrrsO58+fBzB2zf/lL3+JI0eOQCwWIzo6GrfffjuefvppZhu2b9+Ozs5O5j3AmKngrl27UFdXh+joaOzZswf333//pPvmjouYJ8aTHXN9DofDscsFaXR0FJWVlcxFcKbVGpJzQ9Kgg4ODmTt1RwhopVIpampqEB8fj8TERKeshJApJbFYDKVSaTGlRH5AV0NWF03TaGhogFQqRX5+/ryceO0dXUHQ2K9Fz5ABNDX2++TxeABnbJCLywHWLLbUgGn0FL5oVgE0wON+c+5R9FgLbFmqz7wrOzOFWq1mJggVCgV8fHyg1WoRFBSE7OxslyU6pNqZkpKCuLg4Vj9brVYzAxtyuRy+vr4M8WF7+ICE3c40SZ5gKrIzODgIsViMtLS0Gf0u2tU6dGh0rPnsdHd3Qy6XIz09fUY3JDU1NQgNDUVUVBRGRkbQ3Nw8QT9WV1eHwMBAm5qmzhRusjNPmJMdWwmRp8LQ0BCqq6vn3SohF1eyINnbl6avrw+NjY0WmhBnh/mUklwuh5+fH3g8HpMgP1//CUeB+LaoVCrk5eWxeodMfFaIKR/xjLLFgtQp1qBpQA+ABv9/RAcYIzu+ntbTxau7NRhUkFbWmGaHooEwPz5y56jZmS9IJUQgEECn08HDw8PC9doZbwqsYXh4GBUVFXapdo4PeTXP05uvnow43Ofm5s467HYysiMWiyESiZCWlmZXOwzgm9bVZK0zazAajaiqqkJ8fDxCQ0OZfycmJjLHRK/Xo7q6GqmpqU5hYusmO/MEcbp0BNHp7e1FU1MTMjIyEB0dzdrnEl8asoj7+/szJoZsl4ZJqF1PT49LJGVPBq1Wi+rqaiiVStA0DW9vb7uMtLMNctEyGo3Iy8uzaYXPPLqCpI7PJ7rCHFqtFmXllVD7pAFcAcAZ4zoUPfb/s+I8ERk4sW1rMNGo79NCMmI2jeXHx6KYmU9jsQniKBwVFYXU1NQJrtcAZuV67SjIZDJUVlYiPT3d7nf5FEVheHiYOWYGg8HCA2k27fuBgQE0NDQgJydnTlM/1sgOmTpLTU21aZbZZOjq6oJMJkNKSooFCeDxeOByuTCZTOjv70dQUBAEAgH0ej16e3uh1+uxePFi5pwjLbCEhARm9NxoNE47em4vuMnOPGE0GmEwGJjqjj30OeYuvDk5ObMqo84Wer2eIT4ymQy+vr7MIj7fHyYx2ZPL5cjLy3PID50NEIJgMBiQl5cHHo9nkdJuq5F2tkFCHIVCIbKzs+06zjzf6ApzqNVqlJeXIygoCHGJ6Wjo12NEM/b7FPA4SI4QIi5kahKn1lPQ6Ch4CbnwtlPrajxGRkYYR+GkpKQJ5425kaFEIrGbkeFsMTQ0hKqqKixcuJDVm7K5gGjwyHk2Ojo6Yw8kkUiE+vr6ORMdYCLZkUql6O/vdxjRAWBhFGiOhIQEhIaGgqIotLa2Mg7OAoGAmcYyP8fmaipoL7jJzjzx6quvIjk5GUuWLAGfz7f5QmY0GlFbW8u0GOzpwmswGJgWxNDQ0LwM+YhPyFSCalfAdASBTI+QBYnD4VhECjiL9kKj0aCsrGxC5pgjYB5dIRaLp42uMAephBAjTWL6qdbTMJpo+HpyLfQ4zoqpxrKtgWRQkfNMqVQiICCAqZQ5yq3bmYiONRAPJIlEAplMBm9vb+Y8M/eNIgMH2dnZczI2JTAnOyqVCr29vUhNTWXNhNCNyeEmO/MATdO477778MEHH8DLywubN2/G1q1bsXz5cpvcFWu1WlRWVoLP5yMnJ8eh01PmhnxSqRRCoZAhPtOZy5EIC0flKrEFlUrFVBAyMzOnJQjm49lisZgZNXa0DYBSqUR5eTkiIiKQnp7uVJUnmqYZN2IipA8KCmIWcfOLlkKhQEVFxaSVEFcBEfHOZ1pp/CJOjAzDwsKsxsrYAlKpFNXV1cjIyHAJHR65ppGKLLGjEAgE6OrqQk5OzrxDewnZCQoKgkgkQkpKCmsmhG5MDTfZYQF6vR5nzpzBoUOHcOzYMXC5XGzatAlbt27Ftddey0oZb2RkBJWVlU4zkm0O8+qFWCy28F8Zr70gERbOuLDOBnK5HJWVlYiJiZkQSjoTkLFZcsyIDQBZxO1FZMnC6swTcOawJgon04ONjY1ITU2d1zizo0EqIWxqW8y1UUNDQ+DxeEx1caZGhrMF8cHJzMycUcCqs4HcmHR1dUEqlYLD4VhUF+d6TdfpdGhtbQWXy0VKSopTCHe/LXCTHZZhMBhw4cIFHDx4EEePHoVer8emTZtQUlKC66+/fk7tGrFYjNraWsaAy5kXJCIGJIs40V6QkLb6+nokJydPayTmzCDfR2pqKmvjs+NtACarXrAJsh+u6gVEnHV7enowMjLCmM/ZO7qCLRCCYMtKiPnvUyKRwGQyMSSbLVM+sh+LFi2aENboSpBIJKiursbixYvh4+PDkGzSIiTEZzbTUx9//DH8/PyQl5fnsrYUrgo32bEhTCYTLl68iEOHDuHIkSMYHR3Fhg0bUFJSghtuuGHaySaaptHV1YX29naXvHDQNM20bfr7+2E0GhEYGIj4+HinnhyZCsRIzJYeOhqNhiE+CoWCmYZj05eG+IS44nlljoGBAdTX1yMzMxM8Ho9ZxO0aXcECBgcHUVtbi8WLF9vt+7BmyjfeyHC2EIvFqKmpset+2AJSqRRVVVVW94PYJ5AWoaenJ3PMphpAOHHiBJ555hns27cPixYtcolw06sJbrJjJ5hMJnz11VcM8ZFKpVi3bh2Ki4uxbt26CUp8nU6H+vp6jIyMIDc312XLnTRNo7m5Gf39/UhLS2P8fLRaLaNXCQsLc/ogQ/MReXt66IyfhiO+NGQabi7tM5LO7Mqj/gCYVOXx0zHmo8bjtVGzifuYDCaKBkUBfB47CcvEtyUrK2vempD5QK1WM8dMoVAw4ZskEXu6fSWELSsry6WrFkRrNJMWHMmHM7cCCA0NRXBwMLy9vZnrxKlTp3DnnXfinXfeQWZmpt0XXDfcZMchoCgKZWVlOHjwII4cOYLe3l7ceOONKC4uxoYNG6DX67Ft2zakp6fjr3/9q8v+KEwmE2prazE6OmoxOUZEp2QRV6lUFnoVZxlVJKAoCg0NDZDJZA4dkSdGaUR7MRtROPCNZcHAwADy8vJcVhhJ0zQ6OzvR2dk5LfEcH8NA4j7mEl2hM1BoHdRBMmICRdPw8+QhKVyIkHlESJBK4XzGmW0B0iIk55qHh4dF+Ob4c41MKzmasM0XRDM1l1YiqWRLJBJ8/vnnePTRR1FUVITc3Fy89dZbePXVV3HzzTejs7PTJcmOSCTC3r178dFHH6Gvrw/h4eHIzc3Fzp07rUZCAGMOyk8//TTKysrQ1dWFF198ETt37rR4zfi4iLy8PPzf//0fioqKptyeCxcuYPfu3UxcxM9//nN3XIQzg6IoVFdX4+DBgzh8+DDa2toQGBiI2NhYvPvuu0hISHA57QEwdrEkSdi5ublTagGsRTCQRdzRI+nm6et5eXlOc4Eaf0fJ4XCYY2ZNdEpRFBMSm5+f77BR5PmCpmm0traiv78f+fn5sx7ZnWt0hYmiUdquhlJLgWNmUMjjcJCb4Ikgn9kTHtKizs3NtalX1nxhrXph7oFEgkyzs7NdmugQ40O2NFNVVVV4/fXXcfLkSYjFYhQWFuL222/H9ddfj7S0NJtnd7GJzs5OrFixAoGBgfj1r3+N7OxsGAwGnDp1Cq+99hoaGxutvu/KlSv4z3/+g4KCAuzatQt79uyZQHZuvfVW1NbW4pVXXkF0dDT27duHF198EfX19ZOK9Ds6OrB48WLce++9uO+++/DFF19gx44dOHDgALZt22b1PW6y40S4ePEitmzZgoyMDKjVatTX1+O6665DSUkJNm3ahNDQUJcgPiqVChUVFbPO6gK+mbYZHByEQqFgvELCw8PtfnEghI3P5yM7O9spglKtwdpIO1nASbWguroaWq0W+fn5DieQcwXJ6xoaGkJ+fv68bfV1Oh2j8ZkuumJAbkBdrxY87jeJ6DRNw0gBIb585M0ySqKjowOdnZ3Iz893qRa1efWCtKNpmsaCBQuQmJjodFXZmYIQHTb9gC5fvoytW7fiD3/4A773ve/h448/xqVLl3DzzTcjKioKiYmJ8/bXGRgYwPDwMLRaLbhcLnx9fREbGzvpYt7V1QWJRIK4uDgLLVJTUxOUSqXFa4OCgpCcnAwAuOmmm1BdXY2mpqYJvzu5XD6jtn5CQgJ27txpQXY0Gg38/Pxw7NgxbNy4kXk8NzcXmzZtwm9/+1urn7Vnzx4cP34cDQ0NzGP3338/qqqqcPnyZavvcRTZcW6BhgOwb98+3HffffjTn/6E+++/n2k5HDx4EG+//TZ27tyJFStWoKSkBFu2bEFERIRTEh8yyhwbGzunkWwvLy8sWLAACxYsYISAg4ODaGlpga+vLyIiIhgNgS1BXHidwWRvOnC5XAQHByM4OBjp6enMSHtzczN0Oh24XC6EQiHy8vJcluhQFIXa2loolUoUFRWxcrHy8PBAXFwc4uLiLLKUurq6JkRXKDXU//Kyvjmfx9zSacadeSYg2q/e3l4UFha6nJkch8NBUFAQgoKC4OPjg8bGRkRFRUEul+Pzzz+3W8grmyDXrPT0dNaITmlpKbZt24Znn30WDzzwADgcDrZv347bbrsN7e3tCA0Nnfc5rNAb0a1UIyIkDIn+vqBpGn19fWhubrZ6kzk8PIzR0dFJb9pCQ0MtKink2i2TyfDJJ59g7969Vq+789EvkmzJ8cfCy8sLly5dmvR9ly9fxtq1ay0eW7duHd58800YDAanujF1kx0zVFZW4qc//SmOHDnCfIEcDgdpaWl48skn8cQTT6CzsxOHDh3Cf/7zHzz66KNYunQpiouLUVxcjJiYGKcgPmQyJj09nZVRZg8PD8TGxiI2NpZxbx4cHER7ezu8vLwY4jMXoe5UIOZ00dHRSE1NdYpjO1NwOBwEBAQgICAAsbGxKCsrA4fDAZfLxZdffsnoVZyhRThTmEwmppVYVFRkk+qBQCBAVFQUoqKiGN8oMnoMAJ4hSaAQ+L+8rG/OB5oei6CYCYhYf3BwEIWFhS4bjwKMiaqbmpqQm5vLVA/NjQxbW1uZfDh7GhnOFiRkNS0tjTVfo8rKShQXF+MXv/gFHn744Qn7zeFw4O/vP+cFWWeicEE0jD61DuB4oX7EgBijGtdFBiEhIQFVVVVQq9UWRFqv16O7uxtpaWloaWmx+rlcLtfqNrW2toKmaSxcuHBO2zsV/Pz8sGzZMjz77LPIyMhAREQEDhw4gK+//hqpqamTvk8kEk2YkiP2JlKp1KlMLN1kxwy5ubloaWmZtN/N4XCQmJiIRx99FI888gh6e3tx+PBhHD58GE888QQKCgoY4uMIjQ8RjJIJn/nYqU8GgUCA6OhoREdHMye0WCzGlStXIBQKGeIz34sq8QhJSUlxaXM64u4cHBzMmFCSkXaRSISmpiaXuAsnsSIAUFBQYJc7NmK6FxYWhoyMDMjlcvQPyqDQGqEzjVVzeFweOFwuOACig6bfJpqm0djYCKlUisLCQqc93jMBsS0Yn/rt6enJVMrIb1QikaC8vNzimDqLFQC5qUlNTWXNZ6q2thabN2/Go48+ikcffdQm1+ILomH0q3UWj/WrdbggGsaqkLHKi/nEIU3T6OjoQGRk5JRSAJlMBplMBj6fj4CAAERHR4PH44EoTmy1rrz33nu45557EBMTAx6Ph/z8fHz/+99HeXn5lO8bvz223s65wk12xmGmwj4Oh4O4uDj87Gc/w8MPPwyRSIQjR47g0KFDeOaZZ5CVlcUQH3tUJSiKYi7iRUVFdinL8/l8REZGIjIykhFPisVi5qJqLtSdzf5fLd4z5CI+3t3Zy8sL8fHxiI+PZ1qEYrEYra2t8x5ptwX0ej3Ky8shFAqRk5PjEF8m87ZNsNyAxj4tDCYKRooGTAZ4QA2uhoZWO7kvDU3TTOBtYWGhSwlTx4NMj+Xl5U0pqjb/jZpbAdTX18NoNDJuxLNNHWcLJHssOTmZNWPQhoYGbNq0CQ8++CCefPJJm/yGFHrjWEVnHGgAfWodmtXD8PX1tTjHRCIRM8AwGYKDg+Hh4QGBQACNRoPe3l5oNBqkpaUx60hDQwNKSkpY36fk5GRcuHABKpUKIyMjiIqKwq233orExMRJ3xMZGQmRSGTxmFgsBp/Pd6qpRsBNdlgBh8NBVFQUduzYgQceeABSqRTHjh3DoUOHsHfvXqSnp6O4uBglJSXIyMhg/cdnPqm0ZMkSh0wqmZMbiqKY2ArSfiDPTXU3SdM02tvb0d3dPeFu1dVARmenc6ke3yIklbLOzk54eHjMaqTdFtBqtSgvL4evry8WL17sFJWAqEABgn15kI6YYKRoePGM0IyM/k8f1cREVxBXXQ6Hw2iNRkdHUVRU5DKtQ2sgvkbTEZ3x4HK5CAkJQUhICNLT06FUKplzra6uzi5u4eYgafLzyR4bj+bmZmzatAn33HMPfvWrX9nsN6M0GKd8XqEz4Jq0ZObfZNJ1uuu/+c22l5cXPDw80NDQwBhNrlu3Dn//+9/x8MMPz1mgPB18fHzg4+OD4eFhnDp1Cs8999ykr122bBk+/PBDi8dOnz6NwsJCp9LrAO5pLJuCpmkMDw/j+PHjOHz4ME6fPo2EhASG+GRlZc178dBqtUzad05OjtOZApJjMNmEEqkSmFem8vPzXVpHIRKJUFdXh8zMzDn3rM0rZRKJxC45SuOhVqtRVlbG5MA5Q5UJGDunNHoaKh0FLgfw9+JBwB/btvG+NMRVV6FQwGAwoLCw0GUnlQCgu7sbbW1trBtqEiNDiUQCuVwOX19fhvjYosKoVCpRWlrKRO+wgfb2dqxfvx4333wz/vSnP035G5nvRJBCb8ThLvGkz2+KCkSY7zct0sHBQfT09Fh9rVAoRHZ2ttXnaJpGeXk5EhMTERwcjI6ODixfvhzBwcH4zW9+g+zsbBiNRnz66ad45ZVXLKaizKHX61FfXw9gbKLrBz/4AX7wgx/A19cXKSkpAMYMF2maRnp6OlpbW/HYY4/Bw8MDly5dYojLE088gb6+Prz77rsAvhk9v++++3Dvvffi8uXLuP/++92j5992KBQKnDhxAocPH8Ynn3yCyMhIhvjk5+fPegFTKpWoqKhwylBSayDGcoODgxCLxdDr9QgNDUVoaCgGBgag1+udykNnLuju7kZrayuys7NZ00yNzzmjKMoqYWQTJIE9KirKqcThFE2jV2aAdMQIIzX2mAefgwWhggkeOyaTiZmG0+v1FuaP9iKMbMJWRGc8CGGUSCSQSqWMkSGZiJvvcVMqlSgrK0NCQgISEhJY2eauri6sX78emzZtwl//+tdpt5GNBfd03xD61TpYLKA0jUhPATYssGxVGY1GGAwGi8eam5sREhIy5USYRqNBXV0d0tPTGWnCwMAA9u7dixMnTmBgYABhYWGMf87q1autfg4xUByP6667DufPnwcA/Oc//8ETTzyB3t5eBAcHY9u2bdi7d6+FJcP27dvR2dnJvAcYMxXctWsXYyq4Z88et6mgG99gdHQUJ0+exKFDh/Dxxx8jKCgIW7ZsQUlJCZYsWTLtAjY0NITq6mqXSckeD+Le3N/fj97eXlAUhZCQEERGRto1bZwtkBZcT08PcnNzbbYY0TQNhULBEB+dTsdEMLCluyCTMWQxcqZzS6I0olOih4DHgeB/PxGNngafx8HCaA94Cr5Z5IxGIyorK0HTNHJycqBUKm0WXWFrEONDe/sBkYk4UmEEYHHcZku0R0dHUVpayly32EBfXx/WrVuHG264Aa+++uqMyBgbC67FNNb/ECHkYVVEIDx4Y9vA4/Em3Z7q6mpEREQwukStVguZTIaAgADw+XxotVr09PSAy+U6VWV1vnCTnW8x1Go1Tp8+jUOHDuHEiRPw9vbG5s2bUVJSguXLl0+4EF+5cgUjIyPzapM4A9RqNSoqKuDn54fExERIpVIMDg5idHQUwcHBTBnd2fUVxGTP3i04a3Ef8z1uRGvEZpI8m2jq12JES8HH45sFhKbHWlrxoUJEBIyRPYPBgIqKCvB4POTm5losylNFV4SHhztdm4tMWBYUFDg0WsScaEskEmi1WovzbbrjRojOggULkJSUxMo2iUQirF+/HsuXL8ebb745Y/LF5oKr0BtRXt8AIWWEB2Xp9ZSQkDBphXc82dHr9Whvb4dWq4XJZIJQKGSmsZydjM8GbrLjBoCxE+Gzzz7D4cOHcezYMfB4PGzatAlbt27FihUrsGfPHhw6dAhfffUVa34UjsDIyAgqKioQGRmJtLQ0i7uW8WnjAQEBzEi7s7W4KIpCTU0NVCoV8vLyHDrhQ8JdzSMYZuN6LRaLUVtby5pNvy1Q06OBwUjDU2h5tzyqNSE2WIjoIAEzPebh4YHs7OxpF0Br0RVkAXf0aHpHRwe6urqQn5/vVBlqNE0zx00ikVhEfhBhuDlUKhVKS0sRGxvLuAHPF2KxGBs2bEBeXh7efffdWRECRy24brjJjhtWYDAYcP78eSah3WQygcvl4qmnnsKdd97p9BWPyUDSjJOSkqbt2ZMoAbFYjOHhYWbSJiIiwuELkdFoRFVVFYxGI/Ly8pyqIkCM5chxI4LTyZKzSeL34sWLnTopu1Oig1hhhI8nl9kHE0VDq6eREimEN9+EsrIy+Pj4zGkAYLLoCkdYAZDJxIKCAqd3eNZqtYwwXCaTwdvbm6mU8Xg8lJWVISYmBsnJyawcQ6lUio0bNyI9PR0HDhyYdfvWTXYcBzfZcWNSDA8Po6SkBIODg1i5ciU++eQTjI6O4qabbkJJSQnWrFnjMp4h/f39aGhomFMLTq/XMwv40NAQsxBFRERYXcBtCZ1Ox0zBZWdnO3WZmbhem08okQXc398fPT09aG1tdYlxf5WOQqtIB62BglDAAU0DBiONQG8e4gJpVFSMRYtkZmbOW0hrHl0hlUonRFfYUuDc1taGnp4elyA642E0Gi0mCU0mEzP1ExISMu/jNjw8jE2bNmHBggX44IMP5nST4SY7joOb7LhhFR0dHbjpppuQlpaG/fv3w8fHByaTCV999RUOHjyII0eOYGhoCOvXr0dxcTHWrVtn87yquYC4O3d2diInJ2fei6q5J41UKp2wgNuS+Gg0GpSVlblEXtd4mEwmZgGXSCSgaRo0TTM2/a6wL6NaE0RyI5T/Gz0P9uEhwMOIqgrbjcmbR1eIxWMjx6RyERwcPGuhrlipw4maQcg1BmTH+GN1Wgj4XC6T2dXX14eCggKXtmBQq9W4cuUKAgMDIRQKIZVKYTAY5mVkqFAosGXLFoSFheHIkSNzrm67yY7j4CY7bljF+vXrkZaWhhdffNHqBZWiKJSWljLEp7+/HzfeeCOKi4uxYcMGp+jzE4t+iUSCvLw81u9UyQJOiA+fz2eIT2BgIKsLHxnJjoiIQHp6ustOSNA0jaamJgwMDCAkJATDw8OgaXpeC7g9QdM0KBrgANBoxvyAwsPD7fKdjE8cn+1E3Mk6MfYcqQdF0+ByODBSNBZG+OLNO3Mg7etCf3+/yxMdjUaD0tJShIeHM5o8mqYtJuJUKhWCgoKYc266hU+pVKKkpAS+vr44fvz4vKrZZMFNSEhwmar41QKNRsOMwrvJjhsMRkdHZ9yioSgKVVVVDPFpb2/HmjVrUFxcjI0bN7K+8M8EJpMJNTU1UKvVdhHwUhRlUUIn9uxseKuQVGZnHMmeDWiaRn19PYaHh5Gfnw9vb29m0mZwcBASiYTxQCILuLO26Qj5jI6OtojksBfMJ+IkEglGR0endCKWjurxnZe+HIu5MAOPA1yX4I2bF2hRWFjolNXZmYIQnbCwsCnJp0ajYYgPMTIkxGe8PkqlUmHbtm3gcrn46KOP5n18TCYTmpubmRF6N+wHcn1OS0uz6w2Vm+xcpSAL2sGDB3H48GE0NDRg9erVKCkpwaZNmxASEmLzhUGv16OyshIcDge5ubl2986hKApyuZwxMZxP5YJMKqWlpbEWVugImE+P5efnW72zsjbSHhISMuMRY3uBxA2wOco8X4xfwM2jK3x9ffHe1734w+kWWLvq8jjA5w8XIijAtTQ65tBqtSgtLUVISAgWLlw442vMeCNDhUKBkydPoqSkBNdeey2+//3vQ6/X4+TJk6xVhgcGBiCXy5kAXle9eXEV0DTNTIwGBgbafeLTTXa+BaBpGi0tLQzxqaqqwsqVK1FcXIwtW7YgIiKC9R+6RqOxyFRydEvEvHIhFosZ7UBERMS0pnJXSzCpyWRCVVUVDAbDrKbHxo9mBwYGMgu4o1oAxPiQzbgBtkEE9RKJhBGGfzbogQ/qlDBNctW9/NhKBHi5lqEmASE6wcHB89JNkfP0hRdewIULF2AwGODl5YUXX3wRW7duZa3qRdM0RCIR5HI5K5/nxswQGBiIyMhIu5NLN9n5loGmaXR0dODQoUM4fPgwrly5gmXLlmHLli0oLi5GTEzMvE9CZ9e1EO2AWCzG4OAgtFotQkJCEBERYaG5oGkaXV1d6OjoYEVU7UgQkz0ul4vc3Nw5t6WsjbRHREQwlQt7QCaTobKy0mmND62B6MrO1PZh7xcKq69JCPbCRw9e43S/l5lAp9OhtLQUgYGByMzMZGUf9Ho97rjjDgwMDDBTqN3d3bjhhhuYmB02Ilmee+45XLhwgQnfzcvLw6OPPjqpw/PTTz/NRCvcddddFtv73HPP4aOPPoJWq8XSpUvxzDPPIDIyct7beLVAIBA47MbXTXa+xaBpGj09PTh8+DCOHDmCL774AoWFhSguLkZxcTHi4+NnfdEiMRaupGsxb9mYuzcTQpSXl+cUQu+5gozJz9Rkb6YYH7rp5eXFVHxsNRFHPJoWLlyI6OjoCc+bKBpDShPkaiNoAIHePIT48sHnOcd5SNE07nirHNV9IyCyHQ5o0ODgmRtisW1JotPqoyaDTqdjphPZIjoGgwF33XUXOjo6cPbsWUZX09jYiKNHj+LYsWN46qmnsHHjxnn/rfXr1+O2225DUVERjEYjfvGLX6Cmpgb19fUTqkhHjx7Fr371K0gkEjz22GPYuXMn89wDDzyADz/8EG+//TZCQkLwyCOPQCaToayszOGVbTfcZMeN/4GmaQwMDODIkSM4fPgwPv/8c2RnZzPEZybiz4GBAdTX1yMjI8PqQuQKUKvVGBwcRFdXFwwGA/z9/REVFeWU7s0zAWkn+vv723RM3txbhUzEmae0s7EAisVi1NTUYNGiRVbvlk0UjXaxHsMqE7icsUktEw0EeHGRHOHhNIRHqTXgmUNl+KxDAwMFJAZ74tZMH6R4jjLRFc6mj5oMer0epaWlzPnFxvdsNBrx4x//GHV1dTh37pzdTS4lEgnCw8Nx4cIFrFq1inm8r68P11xzDU6dOoWNGzdi586dDNlRKBQICwvDe++9h1tvvRXAmKdYXFwcPv74Y6xbt86u++DGRLjWLYQbNgOHw0F0dDQefPBB7NixA1KplCE+v/3tb7Fw4UKG+Izvx1MUhbKyMiiVSuTm5rr0dIOHhwfkcjk8PDyQn58PuVzOJGf7+/szk12Odm+eCVQqFcrLyxEaGjorsehcwOfzmZwfiqKY8Mjq6moAsEhpnwvhEolEqKurQ1ZW1qSLn1xlglxlgreQAx73G3dlhYaCTGVCuL/jL3c0TaO7rRnfjTfi2a1LwRMI4Sn45q5fpVJBLBajr68PDQ0NThVdMR56vR5lZWXw8/NjjeiYTCbs2LED1dXVDiE6wBhxAWDRtqYoCnfeeScee+wxLFq0aMJ7ysrKYDAYsHbtWuax6OhoLF68GF9++eWcyA5N0y5RGXcVOP7X74bTgcPhICwsDD/5yU9w7733Ynh4GMePH8ehQ4fw/PPPIzExkemZL1y4EA888AD++9//4uLFizZL+7YHiK6Fw+GgsLAQAoEA/v7+WLBgAfR6PdPqam1ttYhfcEY/FDKpFBMTY/eRbC6Xi9DQUISGhiIjI4MhjI2NjYwwfDYj7STKIicnZ0qNhlI7FsJIiA75by6Hxoja8WSHTEjK5XIUFhZarRT6+PggMTERiYmJjD5KIpGgpaXFodEV40GIjo+PD6tE56GHHsJXX32F8+fPOySfjaZp7N69GytXrsTixYuZx//4xz+Cz+fj4Ycftvo+kUgEoVCIoKAgi8cjIiIgEolmtQ3nzp3D9ddf7yY6LOOqIDuff/45nn/+eZSVlTGtmJKSEovXNDQ0YM+ePbhw4QIoisKiRYvwn//8BwsWLAAArF69GhcuXLB4z6233or333/fXrvhlOBwOAgODsb27duxfft2KBQKnDhxAocOHcJ3vvMdBAcHg6Io/OlPf3JpXYtWq0V5eTm8vb2RlZU1occuFAoRGxuL2NhYxr15cHAQHR0djFYlPDwcfn5+Dr9IkUmlxMTEabPHbA0Oh4OgoCAEBQUhLS2N0UG1t7ejrq5u2pZNT08PWlpaZhRlweGMqV/Gg6YBRxtD0zSNuro6KBQKFBQUzKgl6unpibi4OMTFxVlEV1y5csUiuoKtNuFMYTAYmN/K4sWLWWmNUhSFRx55BBcuXMC5c+ccZu/w05/+FNXV1bh06RLzWFlZGf7v//4P5eXlsz7Os63ODAwMYP369Vi3bh2OHz8+p89wwzquCs3OyZMn8cUXXyA/Px/btm2bQHba2tqwZMkS/OhHP8Ltt9+OgIAANDQ0oKioiCmTrl69GmlpafjNb37DvM/LywsBAQH23h2XAMmnkUgkyMrKwqefforg4GBs2bIFJSUlKCoqchlRHmn3kJHZ2Vy8iVZlcHDQIj8pIiICAQEBdr9IEQGvK/gBkZaNWCyGUqlkRtqJPqqzsxMdHR3Iy8ubUcVQrjKhdVAHAY8DIX/suBtMNPRGGonhQoT4OubejqIo1NXVQalUoqCgYN4BvmxHV8wGBoMBZWVl8PLymlPQqjVQFIXHH38cx48fx7lz51hLRZ8tHnroIRw9ehSff/65xSTWSy+9hN27d1vsKwlljouLQ2dnJ86ePYs1a9ZAJpNZVHdycnJQUlKCX//61zPaBpqmcebMGWzfvh2FhYU4duwY87ib8MwPVwXZMQeHw5lAdm677TYIBAK89957k75v9erVyM3NxUsvvWT7jXRx9PT0YP369UhJScGBAwfg7e0NtVqNU6dO4fDhwzhx4gR8fHywefNmlJSUYNmyZU47YaJQKFBRUcFKu4csQmQB5/F4FrEVts6dGhwcRG1t7aQCXmeGVqtljptcLodQKITBYMDixYtn7G1E0zR6hgwQjxhB/S9LgsvhINSXhwVhQnAdsFhQFIXa2lqMjo7OiOhQNA2ZygCDiYK/Jx8+HlP/bkh0BXFw1uv1jAHkXLKnpgKp6JCpPraIztNPP433338f58+fR1paGgtbOjvQNI2HHnoIR44cwfnz55Gammrx/NDQEAYGBiweW7duHe68807cfffdSE9PZwTK+/btwy233AJgrEoTGxs7J4HyhQsXcPvttyMnJwcnT55kttNNeOaOq57sUBSFgIAA/PznP8elS5eY8v4TTzxhQYhWr16Nuro60DSNiIgIbNiwAc8884zLJQ7bGjRNY+nSpcjLy8Pf/vY3qyRGq9XizJkzOHz4MI4dOwY+n4/Nmzdj69atWLlypd2dlCfD0NAQqqqqkJyczLoxHUVRGB4eZhZwc/dmNpKfx4MYH2ZlZSEsLIzVz7YnSGZXf38//P39oVAoZtUmpGkaIxoKo1oKNGj4evIQ4MV1yCJBiI5KpUJBQcG0k1UKjQFl3QoMKLQwmCj4evCRHumLRVF+MyJqs42umA2MRiPKy8shEAiQk5PDyvlL0zR++9vf4p///CfOnTuHzMzMeX/mXLBjxw7s378fx44dQ3p6OvN4QEDApKaZCQkJFtNYwNjo+YkTJ/D2228jODgYjz76KIaGhuY0ek5RFL788kvceuutyMzMxOnTp5l8MTfhmRuuerIjEokQFRUFb29v/Pa3v8X111+PTz75BE8++STOnTuH6667DgDw+uuvIzExEZGRkaitrcUTTzyBlJQUfPrppw7cG+fE4OAgwsPDZ/SjMxgMOH/+PA4ePIijR4/CZDJh06ZNKC4uxurVq+dd0p8ryHRPZmamzYWQ5nffYrEYRqPRQqQ737ZDV1cX2tvbkZubO0Eg6UogREcsFqOgoAA+Pj4wGo0WIa+kTTjbkFedgYJaT8FgpCHgc+At5MJDYLtKG4nlUKvVMyI6RorCuaYh9AxrEOXvASGfC4XGAIXWiGtTQpASNnvXYI1GwxAf8+iK8PDwWbkQE6LD5/ORk5PDSpuMpmk899xzePnll3H27FlkZWXN+zPnisnOobfeegvbt2+3+pw1sqPVavHYY49h//790Gg0WLNmDV5++eUZGV+aTCbweDyQ5Zhs01dffYWbb74ZycnJOHPmDPh8vpvwzBFXPdnp7+9HTEwMbr/9duzfv5953ZYtW+Dj44MDBw5Y/ZyysjIUFhairKwM+fn59tj0qx5GoxGXLl3CBx98gKNHj0KlUmHjxo0oLi7GmjVr7BY90N3djdbWVmRnZ7PiwDob0DSNkZERhvhotVqG+ISFhc2q3UfTNNra2tDb24v8/HyXFojTNI2GhgYMDQ2hsLDQ6rlg3iYkIa/mWpXJqg0aPQWp0gijiQaPy4GJosHncRDqx4eXkH3CQ1EUqqurodVqkZ+fP4HoDKn0qOhRoE2igpeAh8XRfgj1FeJ88xAi/MaIDoFoRIsgbwHWZobPqw1nLbqCEJ+pDCCNRqOF8zZbROf//u//8MILL+DMmTPf+usrITodHR149dVXUVVVhdWrV6OwsBA33HADSktLcdtttyEiIgJnz56Fh4eHm/DMAVc92dHr9fDx8cEzzzyDp556inndnj17cOnSJXzxxRdWP4emaXh4eFiYRLnBHkwmEy5fvsxUfGQyGdavX4/i4mKsXbvWJqnPNE2jvb0dPT09yM3NdfiYPE3TUKlUTF7XbAI3zasg+fn5Tjn+PlNQFIX6+vpZTSqRkFdCfMyrZeZZZxRNY1BuhN5EWxAbtZ6CJ5+DiAA+q4sGRVGoqqqCTqdDQUHBhJatdFSPf5f1oWdYA39PPgxGCnqKRnLImIdOYqjlea/QGGCiaWzOjoSQxw4xI6J6Qn54PJ6FASQhjSaTCeXl5awTnZdffhm/+93vcOrUKSxZsmTen+nKIKSlq6sLS5Yswdq1axEdHY329nZcuHABH330EYqKilBWVoYf/vCHjKeZs3kuuQKuerIDAMuXL0dycrKFQHnr1q3w8vKyqPaYo7a2FllZWRNcNN1gHxRF4cqVKzh48CCOHDmCgYEBrF27FsXFxdiwYQMruilSOZBKpU5LDsZPJxG9RXh4uEW7j5ADuVyOgoICh4VxsgHzFPa5TipZq5YR0hgQFIohFQ0Bn2vhv2OiaBiMFCIDBRaVlJlCMqrDxVYZemQahPgIsCI5BAuCPFBdXQ29Xo/8/Hyr2rRT9WKcbx5Capg3uP/bHqXWiH6FFlH+nkgJ84GX8BtS0TOsQWyQJ65PC7XJnTzRlpHJLpPJxHgk9fb2gsPhIC8vjzWi88Ybb+Dpp5/Gxx9/jBUrVrCwB64Pg8GAO+64A35+fnjjjTcAANnZ2UhMTMS//vUv5lpVUVGBH/zgB9i3b9+3vho2F1wVZGd0dBStra0AgLy8PPz5z3/G9ddfj+DgYCxYsABHjhzBrbfeir///e+MZmfnzp04f/48Vq5ciba2NvzrX//CTTfdhNDQUNTX1+ORRx6Bl5cXrly54jIj1FcDKIpCZWUlE1Ta2dmJNWvWoLi4GBs3bpzTOLf5gpqXl+cS5ECj0UAikWBwcBAKhYJx0g0JCUFrays0Gg3y8/MdpnliAyaTCdXV1dDpdFbbPXPF6Ogoc+yUKi28gmIR6O+DwMAA5m8YTTSMJgqRgUJmTH2maJOo8PynrehXaMEBBxRoBHjycWO0ERlBY+RgMhH+3853QKk1ICrAsnrVJB5FUog3uBwOgryF8OBzIdcYwOEA16aEIC7I9ucsIY2Dg4Po6ekBRVFMQO58oytomsY777yDxx9/HB9++CGjlXRj7Hdw/fXX45FHHkFxcTGuvfZacDgcfPjhhwgICMDFixcZg06VSmWTqve3AVcF2Tl//jyuv/76CY/fddddePvttwEA//znP/H73/8evb29SE9Px69//WsUFxcDGBulvuOOO5gR0bi4OGzcuBHPPPOMSydduzqIEdvBgwdx+PBhNDY24vrrr0dJSQk2btyIkJCQaYmP0WhEVVUVjEYj8vLynD5ryBp0Oh0kEglEIhGGh4fB5XIRHx+PqKgol73wmUwmVFZWwmQyTUkO5gu1Wo2OfjlkIxpoRofh7e2NAP8ACL39EejniXD/2bWxaJrGsx8340qXHAnBY9UZiqLQIhqGv5CDN7ZfA3/vyQno65e6MDiiRawZeaFpGq0SNTZmhcOTz0PHkBpGE40AbwEWRvgiIcR+LQuTyYSqqiqYTCakp6cz7a6RkRGGcIeHh8/qhoGmaezfvx+7d+/G0aNHsWbNGhvugWuAtK8oioJSqcR3v/td7Ny5E//4xz8gk8lw4sQJBAcHQyaT4Te/+Q2WLFmC22+/3a3TmQeuCrLjxtUPmqbR3NzMVHyqqqpw7bXXori4GFu2bLE6HaZSqVBTUwOhUIjs7Gyn9fqZCcyjLCIjIyGVSiGTyZix7IiICIdHCMwURPTK4XCQm5tr8+9FZ6AwNGqESmuESqXCqFIJ9agcPnwjIsNDZhW/IFbqsPODWnjwufD3FIxN2inkMJooqOGJp25KR2F84KTvv9wuw4maQcQEesJbODZ906/QQcjn4p7lCxDiI4TOaILBRMNLwLNovdkaRG9kMBiQn59v8b2YR1fIZLJZRVd88MEHePDBB3Hw4EGsX7/eHrvilKBpGhRFWe0U7N69Gy+99BIyMzPx9ddfMzcx+/btwy9/+Uvs378fy5Yts/cmX1Vwkx03XA5EaHzo0CEcOXIEV65cwfLly7FlyxYUFxcjOjoaTU1N2Lp1K377299i69atNjf0syV0Oh3Ky8sZ11pysRw/li0UChniM9WEjSNBjOmIX4u9WsRGEw2tgYKRAvhcQMClMCwbsjh2YWFh0zpfi0a02HWwDl58Hnw9eJDL5QBo+PgHYEChw5PrU7EkYfLxf53RhA+rB1HTNwKDiQbNAYK8BFibEYbcOMe5tROiM5XeiIBEV4jFYgwNDU1pB3D06FHce++9eP/997F582Z77IrTYXR01EIjqNVq8fe//x18Ph8BAQHMePs999yD//znP3jllVdA0zRkMhkef/xxvPbaa/jhD3/ooK2/euAmOzbCdHldk11Mn3vuOTz22GMAxha5Rx99FAcOHLDwbXD2GAB7gqZp9PT0MMTnyy+/RE5ODtrb27FmzRr885//dOmKjkajQVlZGQIDA5GZmTkpaTOZTBgaGmKmk8zdm+2dnTQZ9Ho9ysvL4enpyZoDLxuYbKQ9IiLCYjoJGDvffnG8EbV9IwjgasHhcBEYGAjRiA6+nny8dPMi+HtO3ZIzUhQ6pBqIRrQQ8rhICvNGmK/jtFdkVJ5op2bTUhx/7P7zn/9AJpOhuLgYHh4euO+++/Dee+/hu9/9rg33wHkhkUhwzz33oLi4GD/+8Y8BACkpKfD29obBYIBcLkdCQgIOHTqEoKAgPPbYYzh9+jQMBgMWLlyIO+64Az/4wQ8cvBdXB9xkx0aYLq9rfBLuyZMn8aMf/Qitra1ISkoCMObI+eGHH+Ltt99GSEgIHnnkEchksjk5cn4bQNM0jhw5gjvuuAMpKSmor69nsmmKi4uRnJzsFIv+TDE6Oory8nKEh4cjPT19xttOUZRFbAUAhvhM5UdjS+h0OpSVlcHX15e18EhbgKIo9A4OoaJtAHL5MMI9KMRFhSEsLIwxgKzqGcZvjtVgRE/D39cbBhMNbyEX25ctwPrMcEfvwqxAxPsajcbqqPxsQNM0Lly4gAMHDuDTTz/F0NAQ8vPz8dBDD2Hjxo0ubXg5V9TV1WHPnj1QKpW4++67weVycezYMbz//vtQKpXo7e1lKjvl5eUAxnzASGvw23jMbAU32bEDrI3Dj0dJSQmUSiU+++wzAGCyVsx9fvr7+xEXFzenrJVvA44fP47vf//7ePHFF/HjH/8YEokER48exaFDh3Du3DksXLiQIT4LFy50auJDMrvi4uKQlJQ0522ladoitsJkMlnEVtiDNJPqVFBQEDIzM536uF9sHcLx6kEMqfQAaAR5cLEimosIzgi0Wi2Cg4OhUqkgNwkxyA9Hp0yLcF8hVqWGICfWtUKDZxtnMVOcO3cOt9xyC5588kkYDAYcO3YMtbW1WL16NUpKSvCjH/1oXtEVBL///e+ZwQUvLy8sX74cf/zjHy0iH371q1/h/fffR09PD4RCIQoKCrB3715cc801zGtWr16NCxcuWHz2rbfeivfff3/e2wiM2Zj88Y9/ZNzTV6xYYRE4TSZON2zYgL/97W+MeNltHMgu3GTHDpiO7AwODiI2NhbvvPMOvv/97wMAaym63xYQovPee+9h69atFs+RBf/YsWM4dOgQzpw5g6SkJBQXF6OkpASLFi1yqkqDTCZDVVUVkpKSWM3sMh8tFovF0Ov1FrEVtmj3qdVqlJWVITQ01OkJZvPgKP5yvgMmikJUgCcjHvYU8LDrO4kI5BlQXV0No9EIiqIm9UFyBdiK6Fy8eBHf+9738NJLL+Gee+5hvu+Ojg4cO3YMn332GY4cOcLKubZ+/XrcdtttKCoqgtFoxC9+8QvU1NSgvr6eEfju378f4eHhSEpKgkajwYsvvogPPvgAra2tTIbc6tWrkZaWZkFAvLy8EBDAHnmtq6vDc889h6NHj2LTpk3417/+BWDse+ByudixYwe6urrw0UcfsfY33bCEm+zYAdORneeeew5/+MMf0N/fz9zx7N+/H3fffTd0Op3Fa9euXYvExET84x//sPVmuxRkMhkaGhpmZFSmUCjw4Ycf4vDhw/jkk08QExPDEJ/c3FyHEh+JRIKamhqkp6cjJibGZn+HhEYS4qPRaBAcHMx4qrAxCj46OoqysjJERkYiLS3NqYkOAPzrv734tEGC1IhvxvlpmkaLWI3Ni8MQZ+yDUChETk4OdDodUy1TKBTw9/dniI81d1uapqE2mODJnzhhRdM0FBojuFxMq/dhAzRNo7a2FkqlEoWFhawRncuXL2Pr1q344x//iPvvv9/u37dEIkF4ePiURrBkhP7MmTPMCPzq1auRm5uLl156ibVtsVaVaWlpwe9+9zt8+umneOSRR7Br1y7muV//+tc4e/YsPvroI/j4+Dj9b8UV4brKzasI//znP/GDH/xgRqVdd2nTOoKDg2fsyBoQEIA77rgDd9xxB5RKJT7++GMcPnwYGzZsQGhoKJPQXlRUZFfiIxKJUF9fj0WLFiEiIsKmf4vD4cDPzw9+fn5ISUlh3Ju7u7tRX1+PoKAghvjMpWqhVCpRVlaG2NhYl9FKydT6CQaDHA4HXA6N2uYOJC/0ZRK/vby8EB8fj/j4eMYHSSwWo7W11WIs28fHBxdbZfi4TgzRiA4BXnzcsDAMGxaFQ8Djol2qwql6MbpkGnA4HGRE+GJdZjgi/G1TKSLeVUqlktWKTmlpKbZt24Znn33WIUQHGLuJATCpN5per8drr72GgIAA5OTkWDz3r3/9C/v27UNERAQ2bNiAZ555Zs7O7STrCgDkcjk8PT3B5/ORmpqKJ598EjweD2+//Tb6+/uxbds2iEQiPP/883jmmWec0tn9aoG7smMHTFXZuXjxIlatWoXKykqLH6C7jWV/qNVqnDp1CocOHcKJEyfg5+eHzZs3o6SkBMuWLbOpvqW3txfNzc0OCScdD5KWTaoWAQEBDPGZiZmcQqFAeXk5EhISkJiYaIctZgfHqgZwuFKElHBvJnTTYDChqnMQ65O9ce/6wmnJr/lYtlQqRa1CgLP9XHB5fAR6e0BtNMFgpFGcE4kbM8Lwj4udkCj1CPMVgqJpSEb1SAr1xgOrEuHnye69KE3TTMxIYWEha623yspKbNy4EU8++SQeffRRhxAdmqZRXFyM4eFhXLx40eK5EydO4LbbboNarUZUVBSOHj2KoqIi5vnXX38diYmJiIyMRG1tLZ544gmkpKTg008/nfV2mBOdn/70p6iurgZFUbjuuuuwe/duxgH9+eefx3vvvYeAgACUlJQgIyMDDz/88PwOghtTwk127ICpyM727dtRW1uL0tJSi8eJQHnfvn245ZZbAAADAwOIjY11C5TtAK1WizNnzuDQoUM4fvw4BAIBU/FZsWIFq46/HR0d6OzsRF5ensPDScfDvF0zPDwMPz8/i6rFeAwPD6OyshLJyclYsGCBA7Z47hgc0eHPn7VhcESHMD8hTCYKHaIhRPkJ8JttBQj1m52oVqMz4OF/V0Ek18CfbwSHA3h4eEJj4oEv4OPGhWH4ol2GtPBv2hZGika7VI07lsRiRTJ77u0kG254eHjGYaszQW1tLTZs2IDdu3fjySefdFgF78EHH8RHH32ES5cuTbDmUKlUGBgYgFQqxeuvv46zZ8/i66+/Rni49cm5srIyFBYWoqysbM4ZVMXFxWhvb8cvfvELtLe34+2330ZmZiZefvllREdHo6enB3v37sWlS5fw17/+1WoCgBvswk12bITp8rqAsf5xVFQU/vSnP+H++++f8BkPPPAATpw4gbfffhvBwcF49NFHMTQ05B49tzMMBgPOnTuHgwcP4tixYzCZTNi0aRNKSkqwevXqObcCaJpGa2sr+vr6UFBQwErgqS2h1+uZds3Q0NAEF10irE5LS3NZL6h2qQonagbRMqiEXC5HYpAHfnRDFuJDZh/L0TOswc+P1MPPkw8fAQ96vR5anQ4arRYSDZAS4gEO3wMpkZYmhs3iUazNCMfW3ChW9ommaTQ2NmJoaAiFhYWsEZ2GhgZs2LABDzzwAH71q185jOg89NBDOHr0KD7//PMZVRJTU1Nxzz334IknnrD6PE3T8PDwsJiEnQ2ef/55fPDBBzh58iRCQkLw7LPP4oUXXkBCQgIiIiLw1ltvISYmBm1tbairq8OWLVtm/TfcmD3cmh0bobS01IKt7969G4BlXtf7778PmqZx++23W/2MF198EXw+H7fccgtjKvj222+7iY6dIRAIsHbtWqxduxYvv/wyLl68yFjgq9VqbNy4EVu2bMENN9ww44WELEBSqRRFRUUukXElFAoRExODmJgYi3ZNZ2cnBAIB9Ho9EhMTbSqstjWSQn3wk2XRuPBVGfxSAnFN3uI5/958hDwIuBzojRR8hDwIPYQQeggh8PSGjqdFiA8XrWIluvQKeHt5wdvHB16enqBpsNbComkaTU1NrBOd5uZmbNq0Cffcc4/DiA5N03jooYdw5MgRnD9/fsYtU5qmJwx+mKOurg4GgwFRUXMjm5GRkSgpKUFISAief/55vPzyyzh27Biam5uxa9cubN++HS+//DJSU1ORnJw8p7/hxuzhruy44cYcYTKZ8OWXXzLuzXK5HOvWrUNJSQnWrl1rdSoHGBs3raurw8jICPLz810ihX0qDAwMoK6uDgEBARgdHQWfz580PsDZQcwP/fz8WLEk+Mu5dnzWKEVUgAe8hDzojRT65FosjPTFHUti8daX3aBMRvhyjVCqVBgcNSLAxwP3LY9BZkL0vHQ1JE9OLBajsLCQtfOsvb0d69evxy233IIXXnjBYdOLO3bswP79+3Hs2DELb52AgAB4eXlBpVJh79692LJlC6KiojA0NISXX34Z+/btQ1lZGRYtWoS2tjb861//wk033YTQ0FDU19fjkUcegZeXF65cuTJnoiuXyzEyMoKSkhLs2bMHt956K7q6uhj5wQMPPICf/exnrBwHN2YGN9lxww0WQFEU/vvf/zLERyQS4cYbb0RJSQnWr1/PtKhGR0exZ88e3HLLLVi2bJlLprCbY2BgAA0NDcjKykJYWBgoirKIrZgqesHZoNVqUVZWhoCAACxatIgVkiZT6fF/59pRPzAKI0WDywHig73w8PVJiA/2wqU2GU7XSyBT68EBEOLNx/JoHoIoxbyTxm1BdLq6urB+/Xps3rwZf/nLXxz6fU72/bz11lvYvn07tFotvv/97+Prr7+GVCpFSEgIioqK8NRTTzEC5Z6eHtxxxx2ora3F6Ogo4uLisHHjRjzzzDOTTnWNx2QTsl988QVKSkpw9uxZZGVl4cqVK/jzn/+Mhx56CMuXL5/7jrsxJ7jJzrcIbOR12dpt9GoARVGorKzEwYMHcfjwYXR1deGGG27AunXr8MYbb8BkMuGjjz5y+NTVfNHX14empibk5OQgJCRkwvMURUEul0MsFmNwcBAURTHEJzg42KnasYTokAwyNqtRRopCbZ8SAyM6BHsLkBvnDw/+N/uu0BjQJdOAz+UgIcQb3sKx54g4nCSN+/r6WojDJ9tGmqbR0tICkUiEwsLCSSuMs0VfXx/WrVuHG2+8Ea+88opTE1db49SpU1AqlSgpKQGfz7dKeJqbm3HnnXcyBqZPP/001q5di7/97W8O2upvN9xk51sENvK67OE2ejWBGLi9++67ePnllxEUFITFixejpKQEGzduRHBwsEu1eQi6u7vR2tqKvLy8GeX30DQNhULBEB+DwYDQ0FBEREQgJCTEoWGtWq0WpaWlCA4ORkZGhlN+H+NH2j09PRniY55wT0TvAwMDKCgoYE0LJhKJsG7dOqxcuRJvvPGGUxFVe4KmaZhMJqxatQpKpRLPPvssNm7cCIFAMIHwUBSFv//97/j3v/8NsViMFStW4K233nLg1n+74SY731LMJa8LsI3b6NWOvr4+rF27FpmZmfjlL3/JuDdXV1dj1apVKC4uxubNmxEeHu6UC+14dHZ2oqOjA/n5+XMiuTRNQ6lUMiPtGo0GISEhCA8PZ829eaYguV3OTHTGY6qE+6GhIfT396OwsJA1oiMWi7Fhwwbk5+fjnXfecSgxdRaoVCrcfPPNGBwcxOOPP44tW7bAw8NjAuEZGRnLVKNp2uZGoW5MDTfZ+ZZiLnldwBjZqaurY36883UbvdrR1taGG264Ad/5znfw2muvMXfENE2jvb0dBw8exJEjR1BWVoZly5ahuLgYW7ZsQXR0tNMtvGSbe3p6WB2VHx0dZYjP6OgogoODmcXblpomjUaD0tJSl8jtmgwURTFBrwMDA0zQa0xMDCutQqlUio0bN2LhwoXYv3+/XYmos8JoNILP50Ov16OkpAT9/f14/PHHUVJSYjHt1tLSgt27d+NnP/sZbrjhBgdusRuAm+x8azGXvC6AXbfRbwPef/99XLlyBS+88MKUGovu7m4cPnwYhw8fxuXLl1FUVITi4mIUFxdjwYIFDl+IiQ6EtEdsZWuvVqsZ4jMyMoLAwECG+LA1Nk3+TllZGcLCwpCenu7w4ztftLe3o6urCwsXLmSqZiToNSwsDGFhYbOuyAwPD2PTpk1YsGABPvjgA5cX088FpFIzNDRkoUsjTskmkwnf/e530dHRgT179mDbtm3w9PREZ2cniouLweVyUVFR4cA9cIPATXa+pZiO7CxcuBA33ngj/vrXv075OWy4jbrxDWiaRn9/P44cOYJDhw7h0qVLTERIcXExkpKS7L4wE68WiUSC/Px8u3kCabVahvjI5fJpwzZnCrVajdLSUkRERLhEQOl06OjoQFdXl0W1jQS9kuOnUqlmVTFTKBRMa/XIkSMul+rOJmpqarBhwwZcuXLFwnvHPBpi27ZtaGpqwhNPPIGioiL84Ac/AJ/Px+XLlx212W6Mg5vsfEsxl7wua5iv26gbk4OmaYjFYhw9ehSHDh3C+fPnkZGRwRAfe1QkSJ4SiRlwlCeQXq9nFm6ZTAYfHx9EREQw7s0zhUqlYpLYU1NTXZ7odHZ2orOzc9q24viK2VQj7WTKyNfXFx9++CGrFTVXxJdffolbb70VlZWVE6YOzQnPbbfdhsrKSigUCsTExEyIAHLDsXCTnW8p5pLXZQ21tbXIysrChQsXsGrVKhtsqRvAGOmQyWQ4duwYDh8+jDNnziA5ORnFxcUoKSlBZmYm66PAxPxQqVQiPz/faRY9Mpk0ODiIoaEheHl5MQu3n5/fpARGpVKhtLQU0dHRSElJcXmi09XVhfb2dhQUFMDf33/G79NqtUzsx/DwMEQiEerq6nDzzTcjPT0d27ZtA5fLxUcffeQSzt62hl6vR2pqKp5//nkmp9Ac5oTne9/7HkQiES5dumTvzXRjGrjJzrcI883rspXbqBuzh1wuZ6a6Tp06hdjYWIb45OTkzJv4UBSFmpoaqNVqFBQUOK1ew2QyMcRHKpVCIBAgPDwcERERCAj4JnNqdHQUZWVliImJQXJysssTne7ubrS1tc2a6IyHwWDA2bNn8eKLL+Lrr79GYGAghEIh9u3bh1WrVrn8cZotKIqy+O1QFAWDwYDVq1dj69at+PnPf271feaExw3nhJvsfItw/vx5q+m65nldr732Gnbu3ImBgYEJY8VsuI26wT6USiU+/vhjHDp0CCdPnkRoaCi2bNmCrVu3orCwcNbEx2QyoaqqCgaDAfn5+S4zgWMymSCTyZh2DZfLZXxoWlpaEBcX5xDNE9vo6elBa2vrnEf/rUGr1eL222+HRCJBSkoKTp06hYCAAGzduhXf/e53sXLlStYW89///vc4fPgwGhsb4eXlheXLl+OPf/yjReTDr371K7z//vvo6emBUChEQUEB9u7di2uuuYZ5jU6nw6OPPooDBw4w2YEvv/zyvENoW1tbUVFRgWXLlsHPzw8BAQF47rnnUFFRgQMHDkxKbMYTJTecC26y44YbVxHUajU++eQTHDp0CB999BH8/PywZcsWlJSUYOnSpdMuWEajEZWVlaBpGrm5uS5DdMaDjGT39vYyxCcyMhLh4eEICQlx2UWpt7cXLS0tyMvLQ2BgICufqdfrcccdd0AkEuHTTz9FUFAQ9Ho9zp49i8OHD+PYsWP4xz/+MaUn12ywfv163HbbbSgqKoLRaMQvfvEL1NTUoL6+nmmb7d+/H+Hh4UhKSoJGo8GLL76IDz74AK2trQgLCwMwli/14Ycf4u2330ZISAgeeeQRyGQylJWVzYmY0TQNtVqNLVu2oLy8HGFhYVAoFFi6dCmqq6vh6emJsrIyeHt7uys5Lgg32XHDjasUWq0Wn376KQ4dOoTjx4/Dw8MDmzdvxtatW7FixYoJo8jDw8NoamqCQCBATk6Oy5vHKZVKlJWVIS4uDsHBwUzFx2g0IjQ0FOHh4QgNDXWZRYvEc+Tn57NGdAwGA+666y50dHTg7NmzVmM/TCYTaJq22fkgkUgQHh4+pe6PiKrPnDmDNWvWQKFQICwszGIwor+/H3Fxcfj444+ZwM25YGhoCAEBAaivr0dpaSlkMhnOnj2Lzs5OZGVl4Y033oCfn5+b8LgYXPP2xo2rBp9//jk2b97MmOgdPXrU4vnR0VH89Kc/RWxsLLy8vJCRkYFXXnnF4jU6nQ4PPfQQQkND4ePjgy1btqC3t9eOe+Gc8PT0xObNm/H2229DJBLh7bffBk3TuOuuu5CcnIwHH3wQn376KfR6PQYHB/Gd73wHJ06cQG5urssTnZGREZSVlSE+Ph7JyckICgpCeno6Vq5cyYitW1tbcf78eVRVVWFgYAAGg8HRmz0p+vv70dTUxGpFx2g04sc//jFaW1vx6aefWiU6AMDj8Wx6PigUCgCYtBWu1+vx2muvISAggJkOLSsrg8FgwNq1a5nXRUdHY/Hixfjyyy/ntT1BQUHg8/nIzs7GPffcg0cffRRHjhzBU089hc7OTvzwhz/EyMgIeDweKIqa199yw35wkx03HAqVSoWcnJxJw/F27dqFTz75BPv27UNDQwN27dqFhx56CMeOHWNes3PnThw5cgTvv/8+Ll26hNHRUWzatAkmk8leu+H0EAqFWLduHV5//XX09/fj3//+N7y8vPDAAw8gPj4eK1euRHBwMB599FGXv1tVKBQoKytDQkICEhMTLZ7jcDgICAhAamoqli9fjmuuuQa+vr7o7OzEhQsXUFFRgb6+Puj1egdt/UT09/ejsbERubm5M8ohmwlMJhMeeOAB1NbW4syZMwgPD2flc2cLmqaxe/durFy5EosXL7Z47sSJE/D19YWnpydefPFFfPrpp0x4rkgkglAonHA8IiIiJmT8zRakxUmaHhRFwcPDA9/73vfw05/+FFKpFDfddBMUCoXLtkO/jXC3sdxwGlgbh1+8eDFuvfVW/PKXv2QeKygowE033YRnn33WpuXsbwO6u7tx7bXXwsfHByqVCnK5HOvXr0dJSQluvPFG1hKz7QWFQoHy8nIkJSUhPj5+Vu9VqVRMq0upVCIoKIjJ63LU2P3AwAAaGhqQm5vL2hCAyWTCww8/jEuXLuH8+fOIiYlh5XPnggcffBAfffQRLl26NEFYrFKpMDAwAKlUitdffx1nz57F119/jfDwcOzfvx933303dDqdxXtuvPFGJCcn49VXX2V1O4mTsslkwttvv42PP/4Yb7zxBmvk0w3bw01L3XBqrFy5EsePH0dfXx9omsa5c+fQ3NzMkBhblrOvdnR2duL666/HjTfeiJqaGnR0dODUqVOIi4vDU089hYSEBNxxxx04ePAglEqlozd3WsjlcpSXlyM5OXnWRAcAfHx8kJiYiGuuuQYrVqxAWFgY45ny3//+F11dXdBoNDbYcusQiURoaGhATk4Oa0SHoig88sgjOH/+PM6cOeNQovPQQw/h+PHjOHfunNUJKh8fH6SkpGDp0qV48803wefz8eabbwIAIiMjodfrMTw8bPEesVhsk8BNDocDmqbB4/Fw9913Y9++fW6i42Jwkx03nBp/+ctfkJmZidjYWAiFQqxfvx4vv/wyVq5cCcC25eyrGUNDQ7j22muxceNGJqCUy+Vi6dKleOGFF9DS0oILFy4gPT0de/fuRUJCAm699VYcOHAACoUCzlYQlsvlqKioQEpKCuMZNR94eXlhwYIFKCoqwrXXXovo6GgMDQ3hiy++wFdffYX29naoVCoWttw6BgcHUV9fj+zs7Em1NLMFRVF4/PHH8cknn+DMmTNzIoRsgKZp/PSnP8Xhw4dx9uzZCa3Gqd5HKjkFBQUQCAQWmXwDAwOora3F8uXLbbLdhPBwuVyHOYm7MXe4tgrRjasef/nLX/DVV1/h+PHjiI+Px+eff44dO3YgKipqyiRhUnZ2wzqCg4Px+uuvY926dVaPE5fLRUFBAQoKCvC73/0OtbW1+OCDD/DSSy9hx44d+M53voPi4mJs2rQJQUFBDj3Ww8PDqKioQGpqKuLi4lj/fA8PD8TGxiI2NhYGg4FxH+7o6GDcmyMiIuDr68vKcRCLxaitrUV2djajUZkvKIrC008/jSNHjuDcuXNITk5m5XPnggcffBD79+/HsWPH4Ofnx9yUBAQEwMvLCyqVCnv37sWWLVsQFRWFoaEhvPzyy+jt7cXNN9/MvPZHP/oRHnnkEYSEhDB6s6ysLJsmjLuvKa4Lt2bHDafBeM2ORqNBQEAAjhw5go0bNzKv+/GPf4ze3l588sknOHv2LNasWQOZTGZR3SHhmb/+9a/tvRtXNWiaRmNjIw4ePIgjR46gtrYWq1atQnFxMTZv3oywsDC7LggymQyVlZVIS0ubt5ncbGE0GiGVSiEWiyGVSiEUCpnYCnP35tlALBajpqYG2dnZjJ/MfEHTNH7729/irbfewtmzZ5GZmcnK584Vkx2Xt956C9u3b4dWq8X3v/99fP3115BKpQgJCUFRURGeeuopFBUVMa/XarV47LHHsH//fgtTQVsQXjdcH26y44bTYDzZId4aH3/8MTZs2MC87r777kNHRwdOnz7NCJT37dvH5NYMDAwgNjbWLVC2MWiaRltbGw4dOoTDhw+jvLwcy5cvR3FxMXNXbkviQ4hOenq6Q7UnwJjod2hoCGKxGBKJBDwejyE+M618SSQSVFdXIysri7XpKJqm8dxzz+Hll1/G2bNnkZWVxcrnuuGGq8FNdtxwKKbL61q9ejWkUin+9re/IT4+HhcuXMADDzyAP//5z3jggQcAjDmpnjhxAm+//TZTzh4aGpqzk6obswdN0+ju7maIz1dffYUlS5aguLgYxcXFiIuLY5X4DA0NoaqqCgsXLkR0dDRrn8sGKIqyiK0AwBCf4OBgq+PKUqkU1dXVWLRoEWsCW5qm8dJLL+FPf/oTPvvsM+Tl5bHyuW644Ypwkx03HIrp8rpEIhGeeOIJnD59GjKZDPHx8fjJT36CXbt2MYunu5ztXKBpGv39/Th8+DAOHz6MS5cuITc3FyUlJSguLkZiYuK8iA8hOhkZGYiKimJxy9kHTdMYHh5miI/JZEJYWBgTW8Hj8Zj9YZvo/P3vf8fvf/97nDp1CkuWLGHlc91ww1XhJjtuuOGGzUDTNAYHB3H06FEcPnwY58+fR2ZmJkN80tLSZkV8SAXEFYjOeNA0jZGREYjFYgwODkKn08Hf3x8KhQILFy5kTXNE0zRef/11PPPMMzh58qTNppPccMOV4CY7brjhhl1A0zRkMhmOHTuGQ4cO4cyZM0hNTUVxcTFKSkqQkZExpSOtRCJBTU0NMjMzERkZacctZx80TaOvrw+NjY0QCoUwGAwIDg5GREQEwsLC5hzAStM03nnnHTz++OM4ceLEpFlTbrjxbYOb7Ljhhht2B03TUCgU+PDDD3Ho0CGcPn0acXFx2LJlC7Zu3Yrs7GwL4nPs2DFwuVwsWbLEJqZx9gYRVxPNEXFvHhwcxOjoKOPeHB4eDg8Pjxl9Jk3T2L9/P3bv3o1jx47hO9/5jo33wg03XAduU0E33LACNgJKV69eDQ6HY/G/2267zY574bzgcDgIDAzEnXfeiaNHj2JwcBC//vWv0dnZibVr1yI7OxtPPvkkrly5gnfeeQd33303jEbjVUF0hoeHmSkyIq4m7s1Lly7FihUrEBoaCpFIhIsXL+LKlSvTujfTNI0PPvgAu3btwgcffOAmOm64MQ5uU0E33LACElB69913Y9u2bROe37VrF86dO4d9+/YhISEBp0+fxo4dOxAdHY3i4mLmdffeey9+85vfMP92O69ah5+fH2677TbcdtttUKlU+OSTT3Do0CFs2LABRqMR27ZtQ0REBEwmk0tP2MnlcsYXaLJxeS8vL8THxyM+Ph46nY4RN7e0tMDPz48RN/v7+zPvOXbsGB588EG8//77WL9+vb12xw03XAZusuOGG1awYcMGC2+f8bh8+TLuuusurF69GgDwk5/8BP/4xz9QWlpqQXa8vb1dXl9ib/j4+GDbtm0wmUw4duwYfv7zn6O3txe33HILPD09sXnzZmzduhXLly8Hn+86lzCFQsFEWsxUjOzh4YG4uDjExcVBr9cz7s179+7FV199hfXr1yM5ORm//OUvsW/fPmzevNnGe+GGG64JdxvLDbuBpmmny1SaK6YLKCX417/+hdDQUCxatAiPPvqoSwRqOgMOHDiAe+65Bx988AF++9vfMjYE//znP0FRFO68806kpKTgpz/9Kc6cOQO9Xu/oTZ4SJI09JSVlzpYIQqEQMTExyMvLwx/+8Ac89NBDqKiowJ49exAQEIArV67gypUrNvmN/f73v0dRURFTWSopKUFTUxPzvMFgwJ49e5CVlQUfHx9ER0fjhz/8Ifr7+y0+x93adcNRcAuU3bALVCoVfHx8HL0Zc8J4Z2cA0Ov1uPfee/Huu++Cz+eDy+XijTfewJ133sm85vXXX0diYiIiIyNRW1uLJ554AikpKf/f3r3H1ZznfwB/ndShm8bpfigluYwat2pWLFHThXIam8plaLbJmhHblFmsNbnsmjHDThKNZSeWYhYlbHNhVDYNU8mDZNVIIh3XHGpUp3r//mj7/uaosKZOdXo/H4/zwPl+vt/H++Nx5H0+t7dK8ULW0s2bN+Hg4IAvv/yyzROw6+vrcerUKRw4cACHDx9GbW0tfH19IZPJMGXKlBde1KsOjx49Ql5eHuzs7NqlSGmz9PR0BAUFISYmBv369UNKSgqOHj0KIyMjzJgxA1FRUe121pS3tzeCg4Ph7OyM+vp6rFy5EhcvXkRhYSH09fWhUCgQEBCAsLAwjBw5EpWVlYiIiEB9fT1yc3OF57i5uWHIkCEtpnaNjIzaJU7G2sLJDlOL4OBgGBgYYOvWrcJ/RI2NjdDS0uryRTtbS3Y2btyIHTt2YOPGjUKB0hUrViAlJaXNQoR5eXlwcnJCXl4exowZo6bou6d79+69cBHMhoYGnD59GgcPHsThw4fx6NEjeHt7w9/fHx4eHtDT0+vgaNv2+PFj5OXlwdbWtl2rjP/73/9GQEAANm/ejLffflv491NbW4vvvvsOycnJWLVqVYdVNr979y7MzMyQmZnZ5vb2nJwcuLi44Pr160KS5+bmhlGjRiEmJqZD4mKsLZzsMLXIysrCtGnTUFZWBiMjIyHBkcvlXX5Ny8sUKG0NEaF3797Ys2cPgoKC1BF6j9PY2IizZ88KhUrv3r0LT09P+Pv7w8vLCwYGBmqLpTnRsbGxgY2NTbs99/vvv8ebb76JDRs2YOHChZ3yReHHH3+Evb09Ll68CAcHh1bbnDhxAp6ennj48KGwmNrNzQ2XLl0CEcHc3Bw+Pj6Ijo6GoaGhOsNnPRCv2WFqIZVKheKcQNPW7c2bN2PQoEH4/PPP27yvK+biSqUSSqWyxQF4vXr1QmNjY5v3Xbp0CUqlstud/NudaGlpYdy4cdi0aRN+/PFHpKenw97eHuvWrYONjQ2Cg4Oxb98+KBSKDv1sVVVVIS8vDwMHDmzXRCcnJwe/+c1v8Oc//7nTEh0iQmRkJCZMmNBmolNTU4Ply5dj9uzZKrvG5syZg3379iEjIwOrVq3CoUOHMGPGDHWFznowHtlhHa55umr8+PGYMmUKoqKiMG/ePBQVFWHJkiV47733AKBLTWf90gKlV69eRWJiIqZOnQoTExMUFhYiKioKurq6yMnJ6dbbp7ujxsZGFBQU4ODBg0hOTkZxcTHc3d0hk8kwbdq0F65M/iKaEx0rKysMGjSoXZ4JAPn5+fD19cXKlSsRFRXVaf9WFi1ahH/961/IyspqdVeZUqnEzJkzUVZWhoyMDJVk52k8tcvUhhhTk8TERBo+fDgNGDCAXF1d6dy5c8K1hoYG4ff19fVERPT1119TbGwsVVZWqjtUSk9PJwAtXvPnzyciooqKCgoJCSGpVEp9+vShoUOH0qZNm6ixsZGIiMrKymjixIkkkUhILBaTnZ0dLVmyhO7fv6/2vjBVjY2NVFhYSGvXrqVRo0aRjo4OeXh40JYtW6i0tJSqqqqourr6pV537tyhtLQ0unDhwks/o7XXmTNnSCKR0F/+8hfhM9YZwsPDacCAAVRSUtLq9bq6OvL396fXXnuN7t2799znNTY2ko6ODu3fv7+9Q2VMBY/ssA7VPKpTUVGBuLg4fPTRR5gzZw5iY2PRr1+/Vu+h/47wvPPOO7hw4QK++OKLNofLGfsliAhXr14VRnzy8/Mxfvx4yGQyTJ8+HRYWFi88glJdXY3c3Fz0798fdnZ27TbycvnyZfj4+ODdd9/F6tWrO23qavHixUhJSUFGRgbs7e1btFEqlQgMDERxcTHS09Nhamr63OcWFBTA0dHxmQudGWsPvGaHdZiGhgZoaWnh+vXrkMlkwhZUJycn9OvXD0qlstX7RCIRHj9+jKKiIkyaNAmvvvqqOsNmPYhIJMLgwYOxfPlynD17FsXFxfDz88OhQ4cwbNgweHp6Ii4uDjdu3HjmGp+ffvoJeXl5kEql7ZroFBUVwdfXF6GhoZ2W6ABNU1d79+5FUlISDA0NIZfLIZfLhRIW9fX1CAgIQG5uLhITE9HQ0CC0aT4D6erVq1i7di1yc3NRWlqKtLQ0zJw5E6NHj8b48eM7pV+s5+CRHdahTp06hblz58Le3h579uzBmjVrIJfLkZyc3Oq6leaRoGPHjuHDDz/E+++/j7feeqvN9TxEJJQQ6CrrfVj3R/+tSp6cnIzk5GScPn0ao0ePhr+/P2QyGWxsbITPW2FhIQ4cOIBZs2bB3t6+3T6HJSUl8Pb2RmBgIDZu3PjMivAdra0+JSQkICQkBKWlpbC1tW21TXp6Otzc3HDjxg3MnTsXBQUFqKqqgpWVFaZNm4bo6GhIJJKODJ8xXrPDOoZSqaQFCxaQlZUVLViwgGpra4moaR2OkZERKRSKVu9rXruzZMkS8vT0pIKCAiIiYZ1C868KhYLu3LnzzBiOHj1KaWlp7dKfriIzM5N8fX3J0tKSAFBKSorKdblcTvPnzydLS0vS1dUlLy8vKioqUmlTU1ND4eHhZGxsTHp6euTn50c3btxQYy+6l8bGRqqoqKD4+Hjy8PAgbW1tGjVqFK1evZpSU1PJzMyMZs+e/YvW+jz9KiwsJGtra1q0aJHKejbG2MvhaSzWIUQiERwdHfHZZ58hPj4eYrEYRIQhQ4bA0tJS2IL+NC0tLfz000/Iz8/HsGHDMHToUOF5P/fPf/4TMpkMw4cPx4oVK1BeXg6gaeoMAO7fv49//OMf+OMf/9iBvVS/5gKlcXFxLa4REfz9/VFSUoLU1FTk5+dj4MCB8PDwQHV1tdAuIiICKSkp2L9/P7KyslBVVQVfX1/h746pEolEsLCwwMKFC/Htt9+ioqIC4eHhyMjIwMyZM9G/f3/Y2Njg8uXL7bKdvby8HFOnToW3tzdiY2M7dUSHMY3RyckW60GaR2XGjRtHCxcuVHmP6P9Hdb766isaPXo0ffHFFy3aNPvmm2/o7NmzlJCQQO7u7uTr60sPHjwQrp8+fZrGjRtHn376KRERPXnyROO+IeOpkZ0rV64QAGE0jKhpZ5tEIqEdO3YQEdHDhw9b7H4pLy8nLS0t+vrrr9UWe3dXVlZGgwYNot/+9re0a9cumj59urAr74MPPqDs7Gx6/Pjx/zyic/XqVRo8eDCFhIQIuxIZY78cf2VgatM8OrN27VphvU5rawGOHz8OY2NjjB07FkDrBwuOHz8ezs7OCAkJwf79+3H+/HmVmlPnz5/H48ePMXnyZABAnz59NP4bcm1tLYCmvjbr1asXxGIxsrKyADSda6JUKuHp6Sm0kUqlcHBwQHZ2tnoD7qbKy8sxefJkuLu7Y8eOHZg/fz5SU1Nx+/ZtREdHo6SkBG+88QZGjhyJlStXIjc395mHTTa7c+cOpk2bBhcXF+zcuZPPYmKsHWn2T3/WJXl4eLQ6DaOlpYXa2lr88MMPGDx4MEaMGCG83+zJkydYtmwZ/P39MWTIEMhkMhw6dAhOTk7Iz88H0DSFdeHCBVRXV+PYsWMYPnw4wsLCUFpa2mo8rSVT3dGwYcMwcOBArFixApWVlairq8PHH38MuVyOiooKAIBcLodYLG6x7d/c3Bxyubwzwu521q5di0mTJuHzzz9X+Wz27dsXs2bNwsGDB3H79m1s2LABt2/fhp+fH0aMGIFly5YhOzu71enCe/fuwc/PD46Ojti9ezcnOoy1M052WJdSUlKC69evY+fOnYiMjMSJEyegUCiE6wkJCdi6dStkMhliYmIwdOhQfPLJJ0hNTYWLiwuApi2u6enpAAADAwPExMTg/PnziI6OBtAyuWkeXWpoaGhx7e7dux3W1/amo6ODQ4cOoaioCBKJBHp6esjIyICPj89z//OkLnR6dVe3efNm7Nix45kjhfr6+ggICEBSUhLkcjm2bNmCR48eITAwEEOHDkVkZCROnTqF+vp6VFZWQiaTwc7ODnv37oW2trYae8NYD9Gpk2iMtUKpVNLevXvJzc2NxGIx9e3bl1asWEE3b96kBQsWkLOzs0r7jz/+mF555RWqrq4mIqLt27dTv3796Pvvvxfa7N69m6ysrCg7O1t479GjR/TNN9/QyZMnW43j1q1bJBKJ2rze2dDKbqxmDx8+FHarubi40HvvvUdERN999x0BUFnfRET02muv0Ycfftih8TKi2tpaSktLo9DQUDIxMSFjY2MyMTEhLy8vqqmp6ezwGNNYPLLDuhxtbW3MmTMH6enpqKmpQXx8PLS1taGnpwdnZ2dUVlbixIkTKC8vR2xsLGJiYjBu3Djo6enhwYMHyM3Nhb29PX71q18Jz/Tz84NcLhemEFJTU+Hl5YW1a9di7ty5MDMzw/bt21WmGI4fPw6JRNItDzU0MjKCqakpiouLkZubC5lMBgAYO3YsdHR0VNY3VVRUoKCgAK6urp0Vbo8hFovh4+ODnTt3oqKiAgkJCbCzs0NKSgp69+7d2eExprF4vJR1aSKRCLNnzxb+7Ofnh5ycHLz55ptwdnaGgYEBbt++jZCQEABN02CZmZmYMmUKAKCurg5isRiXLl2CSCTCwIEDcf/+fYSFhWHNmjUIDQ2FWCzGvn37sH79eri6usLR0REAkJiYiClTpsDc3Fzt/W7LzwuUAsC1a9dw/vx5oUDpgQMHYGpqCmtra1y8eBG///3v4e/vLyxINjIyQmhoKKKiomBsbAyJRIKlS5fC0dERHh4endWtHklbWxt+fn7w8/Pr7FAY03ydPbTE2Mu6fPky/fDDD2RjY0MPHz4kIqL4+HiysLCgmTNnqmzdDQoKol//+tfU0NBAsbGxJBKJaPTo0bRx40YqLy8nIqKpU6fS5s2biYjo3r171KdPHzpw4ID6O/YMzytQunnzZhowYADp6OiQtbU1/elPfxIOdGz25MkTCg8PJ4lEQrq6uuTr60tlZWWd0BvGGFMPTnaYxqiurqYVK1aQtbU1BQYG0pdffkmlpaX0/vvvk4GBAR0+fJiIiMaOHUtBQUEUExNDrq6uZGhoSMOHDycLCwvh/J/du3eTkZERVVRUdGaXGHtp69evJycnJzIwMCBTU1OSyWT0n//8R7heV1dHf/jDH8jBwYH09PTI0tKS3nrrLSH5b8YnbjNNwLWxmMa5ceMGrly5gsDAQBARbG1t8fbbb2Px4sVobGyEq6srfHx8hN1ZN27cwFdffYXDhw8jMjISHh4e8PLygr6+PpKTkzu5N4y9HG9vbwQHB8PZ2Rn19fVYuXIlLl68iMLCQujr60OhUCAgIABhYWEYOXIkKisrERERgfr6eqFoLwC8++67OHr0KHbt2gVjY2NERUXhwYMHyMvL4y3yrNvgZIdptMLCQujp6cHGxgZA0xbrdevW4e9//zuys7PRv3//FvcoFApIpVLs3LkTs2bNUnPEjHWMu3fvwszMDJmZmZg4cWKrbXJycuDi4oLr16/D2toaCoUCpqam2LNnD4KCggAAt27dgpWVFdLS0uDl5aXOLjD20ng3FtNor776qpDoAE0Lnpu/yc6bNw+JiYnIycnBiRMnhEP1vv32W2hpaWHSpEmdFHX3dOrUKfj5+UEqlUIkEuHw4cMq15sXkkulUujp6cHb2xvFxcUqbdzc3CASiVRewcHBauyF5mo+r+pZFcYVCgVEIhFeeeUVAHziNtMcnOywHoWIYGlpibi4OIwaNQrR0dEICQnBsWPH8PDhQwDA/v37MWXKFEil0s4NtptpjyKlABAWFoaKigrhtX37dnV1QWMRESIjIzFhwgQ4ODi02qampgbLly/H7Nmz0bdvXwB84jbTHLz1nPUozacEW1tbY9OmTdi0aRNu3bqFuro62NjY4NGjR0hJScHf/va3To60+/Hx8YGPj0+r14qLi3HmzBkUFBQIZUC2bdsGMzMz7Nu3D++8847QVk9PDxYWFmqJuacIDw/HhQsXhBppT1MqlQgODkZjYyO2bdv23OcRn7jNuhke2WE9nlQqFaa6xGIxYmJi+OyTdvYiRUqbJSYmwsTEBCNGjMDSpUvx+PFjtcaqaRYvXowjR44gPT0dAwYMaHFdqVQiMDAQ165dw/Hjx4VRHQCwsLBAXV0dKisrVe65c+dOlzp/irHn4WSHsZ/p06cPlixZwj/I29mLFCkFgDlz5mDfvn3IyMjAqlWrcOjQIcyYMaMTI+++iAjh4eFITk7GyZMnYWtr26JNc6JTXFyMEydOwNjYWOU6n7jNNAVPYzHGOlxzkdLQ0FBIJBL06tULHh4eLaa9wsLChN87ODjA3t4eTk5OOHfuHMaMGaPusLu1RYsWISkpCampqTA0NBTW2BgZGUFXVxf19fUICAjAuXPncOzYMTQ0NAhtJBIJxGIxn7jNNAYnO4wxtRg7dizOnz8PhUKBuro6mJqa4vXXX4eTk1Ob94wZMwY6OjooLi7mZOd/FB8fD6Bph9vPJSQkICQkBDdv3sSRI0cAAKNGjVJpk56eLtz32WefQVtbG4GBgXjy5Anc3d2xa9cuPmOHdSuc7DDG1MrIyAgAhCKl69ata7PtpUuXoFQqYWlpqa7wNMbzjlCzsbF5bhugaWp3y5Yt2LJlS3uFxpjacbLDGGsXv7RI6dWrV5GYmIipU6fCxMQEhYWFiIqKwujRozF+/PjO6hZjTAPwCcqMsXaRkZGByZMnt3h//vz52LVrF2JjY/Hpp5/i9u3bsLS0xLx587Bq1SqIxWIATWU75s6di4KCAlRVVcHKygrTpk1DdHT0Mw/CY4yx5+FkhzHGGGMajbeeM8YYY0yjcbLDGGOMMY3GyQ5jTON99NFHcHZ2hqGhIczMzODv748rV66otCEirF69GlKpFLq6unBzc8OlS5dU2tTW1mLx4sUwMTGBvr4+pk+fjps3b6qzK4yxl8DJDmNM42VmZmLRokU4c+YMjh8/jvr6enh6eqoUIf3kk0/w17/+FXFxccjJyYGFhQXeeOMNlXIVERERSElJwf79+5GVlYWqqir4+vqioaGhM7rFGHtBvECZMdbj3L17F2ZmZsjMzMTEiRNBRJBKpYiIiMCyZcsANI3imJubY8OGDfjd734HhUIBU1NT7NmzB0FBQQCAW7duwcrKCmlpafDy8urMLjHGnoFHdhhjPY5CoQAAYUv7tWvXIJfLhTN/AKB3796YNGkSsrOzAQB5eXlQKpUqbaRSKRwcHIQ2jLGuiZMdxliPQkSIjIzEhAkT4ODgAABCTainC8Cam5sL1+RyOcRiMfr169dmG8ZY18QnKDPGepTw8HBcuHABWVlZLa6JRCKVPxNRi/ee9iJtGGOdi0d2GGM9xuLFi3HkyBGkp6djwIABwvsWFhYA0GKE5s6dO8Joj4WFBerq6lBZWdlmG8ZY18TJDmNM4xERwsPDkZycjJMnT8LW1lbluq2tLSwsLHD8+HHhvbq6OmRmZsLV1RVAU9V2HR0dlTYVFRUoKCgQ2jDGuiaexmKMabxFixYhKSkJqampMDQ0FEZwjIyMoKurC5FIhIiICKxfvx729vawt7fH+vXroaenh9mzZwttQ0NDERUVBWNjY0gkEixduhSOjo7w8PDozO4xxp6Dt54zxjReW2tqEhISEBISAqBp9GfNmjXYvn07Kisr8frrr2Pr1q3CImYAqKmpwQcffICkpCQ8efIE7u7u2LZtG6ysrNTRDcbYS+JkhzHGGGMajdfsMMYYY0yjcbLDGGOMMY3GyQ5jjDHGNBonO4wxxhjTaJzsMMYYY0yjcbLDGGOMMY3GyQ5jjDHGNBonO4wxxhjTaJzsMMYYY0yjcbLDGGOMMY3GyQ5jjDHGNBonO4wxxhjTaJzsMMYYY0yjcbLDGGOMMY32f6iP3KoxLKNBAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 700x700 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "\n",
    "\n",
    "points = np.nan_to_num(coords, nan=0.0)\n",
    "points = points[:20, :, :]\n",
    "cls_id = np.array(range(points.shape[0])).reshape(-1, 1)  # 根据基团上色\n",
    "# np.random.shuffle(cls_id)\n",
    "\n",
    "categories = np.zeros((points.shape[0], points.shape[1])) + cls_id\n",
    "categories = categories.reshape(-1)\n",
    "points = points.reshape(-1, 3)\n",
    "print(points.shape, categories.shape)\n",
    "\n",
    "\n",
    "# 创建一个新的图形\n",
    "fig = plt.figure(figsize=(7, 7))\n",
    "ax = fig.add_subplot(111, projection='3d')\n",
    "\n",
    "# 获取所有不同的类别\n",
    "unique_categories = np.unique(categories)\n",
    "\n",
    "# 为每个类别分配一种颜色\n",
    "colors = plt.colormaps.get_cmap('tab20').resampled(len(unique_categories))  # tab10', tab20', 'gist_rainbow'\n",
    "# colors = plt.colormaps['tab20c']\n",
    "print(colors)\n",
    "\n",
    "\n",
    "# 绘制点云\n",
    "for i, category in enumerate(unique_categories):\n",
    "    # 找到属于当前类别的点\n",
    "    points_in_category = points[categories == category]\n",
    "    ax.scatter(points_in_category[:, 0], points_in_category[:, 1], points_in_category[:, 2],\n",
    "               c=np.array([colors(i)]), label=f'C {category}')\n",
    "\n",
    "# 添加图例\n",
    "plt.legend()\n",
    "\n",
    "# 设置轴标签\n",
    "ax.set_xlabel('X Label')\n",
    "ax.set_ylabel('Y Label')\n",
    "ax.set_zlabel('Z Label')\n",
    "\n",
    "# 显示图形\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "ef567b16-a1f2-4a00-bc6a-a7d6daceb6cc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define RNADataset Class and Seeding Function\n",
    "class RNADataset(Dataset):\n",
    "    def __init__(self, data_path, npy_dir):\n",
    "        super(RNADataset, self).__init__()\n",
    "        self.data = pd.read_csv(data_path)\n",
    "        self.npy_dir = npy_dir\n",
    "        self.seq_list = self.data['seq'].to_list()\n",
    "        self.name_list = self.data['pdb_id'].to_list()\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.name_list)\n",
    "\n",
    "    def __getitem__(self, idx):\n",
    "        seq = self.seq_list[idx]\n",
    "        pdb_id = self.name_list[idx]\n",
    "        coords = np.load(os.path.join(self.npy_dir, pdb_id + '.npy'))\n",
    "\n",
    "        feature = {\n",
    "            \"name\": pdb_id,\n",
    "            \"seq\": seq,\n",
    "            \"coords\": {\n",
    "                \"P\": coords[:, 0, :],\n",
    "                \"O5'\": coords[:, 1, :],\n",
    "                \"C5'\": coords[:, 2, :],\n",
    "                \"C4'\": coords[:, 3, :],\n",
    "                \"C3'\": coords[:, 4, :],\n",
    "                \"O3'\": coords[:, 5, :],\n",
    "                \"N\": coords[:, 6, :],\n",
    "            }\n",
    "        }\n",
    "\n",
    "        return feature"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "bffd6013-4f5b-42bf-9b05-42bd6041daa9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "seeding done!!!\n"
     ]
    }
   ],
   "source": [
    "def seeding(seed):\n",
    "    np.random.seed(seed)\n",
    "    random.seed(seed)\n",
    "    os.environ['PYTHONHASHSEED'] = str(seed)\n",
    "    torch.manual_seed(seed)\n",
    "    torch.cuda.manual_seed(seed)\n",
    "    torch.cuda.manual_seed_all(seed)\n",
    "    torch.backends.cudnn.deterministic = True\n",
    "    torch.backends.cudnn.benchmark = False\n",
    "    print('seeding done!!!')\n",
    "config = Config()\n",
    "data_config = config.data_config\n",
    "train_config = config.train_config\n",
    "seeding(config.seed)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "85a61f93-e518-4d50-aa87-9e4bc1f74516",
   "metadata": {},
   "outputs": [],
   "source": [
    "train_dataset = RNADataset(\n",
    "    data_path=data_config.train_data_path,\n",
    "    npy_dir=data_config.train_npy_data_dir,\n",
    ")\n",
    "valid_dataset = RNADataset(\n",
    "    data_path=data_config.valid_data_path,\n",
    "    npy_dir=data_config.valid_npy_data_dir,\n",
    ")\n",
    "test_dataset = RNADataset(\n",
    "    data_path=data_config.test_data_path,\n",
    "    npy_dir=data_config.test_npy_data_dir,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "44892589",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'1A9N_1_Q'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_dataset[0]['name']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5dbc500a",
   "metadata": {},
   "source": [
    "### RNA Inverse Folding Framework\n",
    "\n",
    "This framework integrates geometric featurization with GNNs to predict RNA sequences compatible with input 3D conformations.\n",
    "该框架将几何特征化与图神经网络（GNNs）相结合，用于预测与输入三维构象兼容的RNA序列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "e049e40a",
   "metadata": {},
   "outputs": [],
   "source": [
    "def prepare_rna_batch(rna_samples):\n",
    "    \"\"\"将RNA样本批次转换为神经网络可用的张量格式\n",
    "    \n",
    "    参数:\n",
    "        rna_samples: 包含多个RNA样本的列表，每个样本应包含:\n",
    "            - 'seq': 碱基序列字符串(如\"AUCG\")\n",
    "            - 'coords': 原子坐标字典\n",
    "            - 'name': 样本标识名\n",
    "    \n",
    "    返回:\n",
    "        features: 形状[B, L_max, 6, 3]的原子坐标张量\n",
    "        labels: 形状[B, L_max]的碱基类别张量  \n",
    "        valid_mask: 有效位置掩码\n",
    "        seq_lengths: 各样本实际长度\n",
    "        sample_names: 样本名称列表\n",
    "    \"\"\"\n",
    "    tag_list = list(\"AUCG\")\n",
    "    idx2tag = {i: tag for i, tag in enumerate(tag_list)}\n",
    "    tag2idx = {tag: i for i, tag in enumerate(tag_list)}\n",
    "    # KEY_ATOMS = [\"P\", \"O5'\", \"C5'\", \"C4'\", \"C3'\", \"O3'\", \"N\"]\n",
    "    KEY_ATOMS = [\"P\", \"O5'\", \"C5'\", \"C4'\", \"C3'\", \"O3'\"]\n",
    "    \n",
    "    # 初始化维度\n",
    "    batch_size = len(rna_samples)\n",
    "    seq_lengths = [b[\"coords\"][\"P\"].shape[0] for b in rna_samples]  # 获取RNA序列长度\n",
    "    max_len = max(seq_lengths)  # 当前batch最大长度\n",
    "    \n",
    "    # 预分配张量（直接初始化为最终类型）\n",
    "    coords = np.zeros((batch_size, max_len, 6, 3), dtype=np.float32)  # batch, 序列长度，6个原子位置，每个原子坐标\n",
    "    labels = np.full((batch_size, max_len), -1, dtype=np.int64)\n",
    "    mask = np.zeros((batch_size, max_len), dtype=np.float32)\n",
    "    \n",
    "    for i, sample in enumerate(rna_samples):\n",
    "        curr_len = seq_lengths[i]\n",
    "        # 向量化处理原子坐标\n",
    "        atom_stack = np.stack([np.nan_to_num(sample['coords'][atom], nan=0.0) for atom in KEY_ATOMS],\n",
    "                              axis=1)  # N 6 3\n",
    "        # 有效位置标记\n",
    "        valid_pos = np.isfinite(atom_stack.sum((1,2)))\n",
    "        actual_len = min(curr_len, sum(valid_pos))\n",
    "        # 单样本赋值\n",
    "        coords[i,:actual_len] = atom_stack[valid_pos][:actual_len]\n",
    "        mask[i,:actual_len] = 1.0\n",
    "        \n",
    "        # 有标签的话读取标签\n",
    "        seq = np.array([c for c in sample['seq']], dtype=np.str_)  # 字符串转列表再转numpy\n",
    "        labels[i,:actual_len] = [tag2idx[b] for b in seq[valid_pos][:actual_len]]\n",
    "    \n",
    "    features, labels, valid_mask, seq_lengths, sample_names = (torch.from_numpy(coords),\n",
    "        torch.from_numpy(labels),\n",
    "        torch.from_numpy(mask),\n",
    "        np.array(seq_lengths),\n",
    "        [s['name'] for s in rna_samples])\n",
    "    \n",
    "    return features, labels, valid_mask, seq_lengths, sample_names\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "318463dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# prepare_rna_batch([train_dataset[0]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "0d8d9a12-eb92-404f-8cd4-0998d310c1f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "train_loader = DataLoader(train_dataset,\n",
    "        batch_size=train_config.batch_size,\n",
    "        shuffle=True,\n",
    "        num_workers=0,\n",
    "        collate_fn=prepare_rna_batch)\n",
    "\n",
    "valid_loader = DataLoader(valid_dataset,\n",
    "        batch_size=train_config.batch_size,\n",
    "        shuffle=False,\n",
    "        num_workers=0,\n",
    "        collate_fn=prepare_rna_batch)\n",
    "\n",
    "test_loader = DataLoader(test_dataset,\n",
    "        batch_size=train_config.batch_size,\n",
    "        shuffle=False,\n",
    "        num_workers=0,\n",
    "        collate_fn=prepare_rna_batch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "1ed12564-029e-496c-8826-29f98c6b580c",
   "metadata": {},
   "outputs": [],
   "source": [
    "def gather_edges(edges, neighbor_idx):\n",
    "    neighbors = neighbor_idx.unsqueeze(-1).expand(-1, -1, -1, edges.size(-1))\n",
    "    return torch.gather(edges, 2, neighbors)\n",
    "\n",
    "def gather_nodes(nodes, neighbor_idx):\n",
    "    neighbors_flat = neighbor_idx.view((neighbor_idx.shape[0], -1))\n",
    "    neighbors_flat = neighbors_flat.unsqueeze(-1).expand(-1, -1, nodes.size(2))\n",
    "    neighbor_features = torch.gather(nodes, 1, neighbors_flat)\n",
    "    neighbor_features = neighbor_features.view(list(neighbor_idx.shape)[:3] + [-1])\n",
    "    return neighbor_features\n",
    "\n",
    "def gather_nodes_t(nodes, neighbor_idx):\n",
    "    idx_flat = neighbor_idx.unsqueeze(-1).expand(-1, -1, nodes.size(2))\n",
    "    return torch.gather(nodes, 1, idx_flat)\n",
    "\n",
    "def cat_neighbors_nodes(h_nodes, h_neighbors, E_idx):\n",
    "    h_nodes = gather_nodes(h_nodes, E_idx)\n",
    "    return torch.cat([h_neighbors, h_nodes], -1)\n",
    "\n",
    "\n",
    "class MPNNLayer(nn.Module):\n",
    "    # 简单的聚合边特征到节点特征\n",
    "    def __init__(self, num_hidden, num_in, dropout=0.1, num_heads=None, scale=30):\n",
    "        super(MPNNLayer, self).__init__()\n",
    "        self.num_hidden = num_hidden\n",
    "        self.num_in = num_in\n",
    "        self.scale = scale\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "        self.norm1 = nn.LayerNorm(num_hidden)\n",
    "        self.norm2 = nn.LayerNorm(num_hidden)\n",
    "\n",
    "        self.W1 = nn.Linear(num_hidden + num_in, num_hidden, bias=True)\n",
    "        self.W2 = nn.Linear(num_hidden, num_hidden, bias=True)\n",
    "        self.W3 = nn.Linear(num_hidden, num_hidden, bias=True)\n",
    "        self.act = nn.ReLU()\n",
    "\n",
    "        self.dense = nn.Sequential(\n",
    "            nn.Linear(num_hidden, num_hidden*4),\n",
    "            nn.ReLU(),\n",
    "            nn.Linear(num_hidden*4, num_hidden)\n",
    "        )\n",
    "\n",
    "    def forward(self, h_V, h_E, edge_idx, batch_id=None):\n",
    "        src_idx, dst_idx = edge_idx[0], edge_idx[1]\n",
    "        h_message = self.W3(self.act(self.W2(self.act(self.W1(h_E)))))\n",
    "        # 特征聚合, 按源节点聚合，即分组相加\n",
    "        dh = scatter_sum(h_message, src_idx, dim=0) / self.scale\n",
    "        # 随机丢一些边的特征\n",
    "        h_V = self.norm1(h_V + self.dropout(dh))\n",
    "        # skip-connection\n",
    "        dh = self.dense(h_V)\n",
    "        h_V = self.norm2(h_V + self.dropout(dh))\n",
    "        return h_V\n",
    "\n",
    "\n",
    "class Normalize(nn.Module):\n",
    "    def __init__(self, size, epsilon=1e-6):\n",
    "        super(Normalize, self).__init__()\n",
    "        self.gain = nn.Parameter(torch.ones(size))\n",
    "        self.bias = nn.Parameter(torch.zeros(size))\n",
    "        self.epsilon = epsilon\n",
    "\n",
    "    def forward(self, x, dim=-1):\n",
    "        mu = x.mean(dim, keepdim=True)\n",
    "        sigma = torch.sqrt(x.var(dim, keepdim=True) + self.epsilon)\n",
    "        gain = self.gain\n",
    "        bias = self.bias\n",
    "        if dim != -1:\n",
    "            shape = [1] * len(mu.size())\n",
    "            shape[dim] = self.gain.size()[0]\n",
    "            gain = gain.view(shape)\n",
    "            bias = bias.view(shape)\n",
    "        return gain * (x - mu) / (sigma + self.epsilon) + bias\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "102ead4b-e635-464b-a3c2-68bda9f2e9fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "feat_dims = {\n",
    "    'node': {\n",
    "        'angle': 12,\n",
    "        'distance': 80,\n",
    "        'direction': 9,\n",
    "    },\n",
    "    'edge': {\n",
    "        'orientation': 4,\n",
    "        'distance': 96,\n",
    "        'direction': 15,\n",
    "    }\n",
    "}\n",
    "\n",
    "def nan_to_num(tensor, nan=0.0):\n",
    "    idx = torch.isnan(tensor)\n",
    "    tensor[idx] = nan\n",
    "    return tensor\n",
    "\n",
    "def _normalize(tensor, dim=-1):\n",
    "    return nan_to_num(\n",
    "        torch.div(tensor, torch.norm(tensor, dim=dim, keepdim=True)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "394e9ca4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[ 0.9386,  0.2600,  2.1021,  ...,  1.1010, -1.1442, -1.1579],\n",
       "         [-0.1662,  0.0067,  1.1745,  ...,  0.5197,  1.5059, -0.6418],\n",
       "         [ 1.2056,  0.0733,  1.4064,  ...,  0.0062,  0.7198, -2.1814],\n",
       "         ...,\n",
       "         [ 0.0597,  0.0891,  2.1562,  ...,  1.5443, -0.8060, -1.1241],\n",
       "         [ 0.4072, -0.0235,  2.6543,  ..., -0.2354, -0.8811, -1.0525],\n",
       "         [ 0.6184, -0.4741,  0.7277,  ...,  0.5982, -0.0660, -1.2220]],\n",
       "        grad_fn=<AddBackward0>),\n",
       " tensor([[-0.2892, -0.4660,  0.0352,  ...,  0.0078, -0.4173, -1.4975],\n",
       "         [-0.2955, -0.7650,  0.5896,  ...,  0.1860, -0.4048, -1.8184],\n",
       "         [-0.3620, -0.9075, -0.4839,  ...,  0.0288, -0.6469, -1.6082],\n",
       "         ...,\n",
       "         [ 0.2928,  0.5560, -0.4186,  ...,  0.0753, -0.6184, -0.5912],\n",
       "         [ 0.2421,  0.3380, -0.1596,  ...,  0.2078, -0.4872, -0.5683],\n",
       "         [ 0.2178,  0.7794, -0.0307,  ...,  0.4655, -0.5075, -0.4484]],\n",
       "        grad_fn=<AddBackward0>),\n",
       " tensor([[  0,   0,   0,  ..., 127, 127, 127],\n",
       "         [  0,  71,  12,  ...,  82,  78, 103]]),\n",
       " tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n",
       "         0, 0, 0, 0, 0, 0, 0, 0]))"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from torch_geometric.data import Data, Batch\n",
    "\n",
    "\n",
    "# 图结构数据生成器\n",
    "class RNAGraphBuilder(nn.Module):\n",
    "\n",
    "    def __init__(self, edge_features, node_features, num_rbf=16, top_k=30, augment_eps=0.):\n",
    "        super(RNAGraphBuilder, self).__init__()\n",
    "        self.num_rbf = num_rbf\n",
    "        self.top_k = top_k\n",
    "        # 随机增强系数\n",
    "        self.augment_eps = augment_eps\n",
    "        \n",
    "        self.node_feat_types = ['angle', 'distance', 'direction']\n",
    "        self.edge_feat_types = ['orientation', 'distance', 'direction']\n",
    "        node_in = sum([feat_dims['node'][feat] for feat in self.node_feat_types])\n",
    "        edge_in = sum([feat_dims['edge'][feat] for feat in self.edge_feat_types])\n",
    "        self.node_embedding = nn.Linear(node_in,  node_features, bias=True)\n",
    "        self.edge_embedding = nn.Linear(edge_in, edge_features, bias=True)\n",
    "        self.norm_nodes = Normalize(node_features)\n",
    "        self.norm_edges = Normalize(edge_features)\n",
    "\n",
    "\n",
    "    @staticmethod\n",
    "    def build_graph(coord, seq, k_neighbors):\n",
    "        \"\"\"将坐标和序列转换为图结构\"\"\"\n",
    "        num_nodes = coord.shape[0]\n",
    "        # 节点特征：展平每个节点的7个骨架点坐标\n",
    "        x = torch.tensor(coord.reshape(num_nodes, -1), dtype=torch.float32)  # [N, 7*3]\n",
    "        \n",
    "        # 边构建：基于序列顺序的k近邻连接\n",
    "        edge_index = []\n",
    "        for i in range(num_nodes):\n",
    "            # 连接前k和后k个节点\n",
    "            neighbors = list(range(max(0, i-k_neighbors), i)) + \\\n",
    "                       list(range(i+1, min(num_nodes, i+1+k_neighbors)))\n",
    "            for j in neighbors:\n",
    "                edge_index.append([i, j])\n",
    "                edge_index.append([j, i])  # 双向连接\n",
    "        \n",
    "        edge_index = torch.tensor(edge_index, dtype=torch.long).t().contiguous()\n",
    "        # 节点标签\n",
    "        y = torch.tensor([Config.seq_vocab.index(c) for c in seq], dtype=torch.long)\n",
    "        return Data(x=x, edge_index=edge_index, y=y, num_nodes=num_nodes)\n",
    "\n",
    "\n",
    "    def _dist(self, X, mask, top_k, eps=1E-6):\n",
    "        mask_2D = torch.unsqueeze(mask,1) * torch.unsqueeze(mask,2)  # 两两之间求掩码 B, N -> B, N, N\n",
    "        dX = torch.unsqueeze(X, 1) - torch.unsqueeze(X, 2)  # 两两之间求距离 B, N, 3 -> B, N, N, 3\n",
    "        D = (1. - mask_2D)*10000 + mask_2D* torch.sqrt(torch.sum(dX**2, 3) + eps)  #  B, N, N 求欧式距离, 无效值距离设置10000的很大值\n",
    "        D_max, _ = torch.max(D, -1, keepdim=True)  # 获取每行的最大值\n",
    "        D_adjust = D + (1. - mask_2D) * (D_max+1)  # 无效值设置为最大值+1, 不会被选中\n",
    "        D_neighbors, E_idx = torch.topk(D_adjust, min(top_k, D_adjust.shape[-1]), dim=-1, largest=False) # 选择topk近邻\n",
    "        return D_neighbors, E_idx  # 返回每个节点的邻居特征和邻居索引\n",
    "\n",
    "\n",
    "    def _rbf(self, D, num_rbf):\n",
    "        D_min, D_max, D_count = 0., 20., num_rbf\n",
    "        D_mu = torch.linspace(D_min, D_max, D_count, device=D.device)\n",
    "        D_mu = D_mu.view([1,1,1,-1])\n",
    "        D_sigma = (D_max - D_min) / D_count\n",
    "        D_expand = torch.unsqueeze(D, -1)\n",
    "        return torch.exp(-((D_expand - D_mu) / D_sigma)**2)\n",
    "\n",
    "\n",
    "    def _get_rbf(self, A, B, E_idx=None, num_rbf=16):\n",
    "        if E_idx is not None:\n",
    "            D_A_B = torch.sqrt(torch.sum((A[:,:,None,:] - B[:,None,:,:])**2,-1) + 1e-6)\n",
    "            D_A_B_neighbors = gather_edges(D_A_B[:,:,:,None], E_idx)[:,:,:,0]\n",
    "            RBF_A_B = self._rbf(D_A_B_neighbors, num_rbf)\n",
    "        else:\n",
    "            D_A_B = torch.sqrt(torch.sum((A[:,:,None,:] - B[:,:,None,:])**2, -1) + 1e-6)\n",
    "            RBF_A_B = self._rbf(D_A_B, num_rbf)\n",
    "        return RBF_A_B\n",
    "\n",
    "\n",
    "    def _quaternions(self, R):\n",
    "        diag = torch.diagonal(R, dim1=-2, dim2=-1)\n",
    "        Rxx, Ryy, Rzz = diag.unbind(-1)\n",
    "        magnitudes = 0.5 * torch.sqrt(torch.abs(1 + torch.stack([\n",
    "              Rxx - Ryy - Rzz, \n",
    "            - Rxx + Ryy - Rzz, \n",
    "            - Rxx - Ryy + Rzz\n",
    "        ], -1)))\n",
    "        _R = lambda i,j: R[:,:,:,i,j]\n",
    "        signs = torch.sign(torch.stack([\n",
    "            _R(2,1) - _R(1,2),\n",
    "            _R(0,2) - _R(2,0),\n",
    "            _R(1,0) - _R(0,1)\n",
    "        ], -1))\n",
    "        xyz = signs * magnitudes\n",
    "        w = torch.sqrt(F.relu(1 + diag.sum(-1, keepdim=True))) / 2.\n",
    "        Q = torch.cat((xyz, w), -1)\n",
    "        Q = F.normalize(Q, dim=-1)\n",
    "        return Q\n",
    "\n",
    "\n",
    "    def _orientations_coarse(self, X, E_idx, eps=1e-6):\n",
    "        V = X.clone()\n",
    "        X = X[:,:,:6,:].reshape(X.shape[0], 6*X.shape[1], 3) \n",
    "        dX = X[:,1:,:] - X[:,:-1,:]\n",
    "        U = _normalize(dX, dim=-1)\n",
    "        u_0, u_1 = U[:,:-2,:], U[:,1:-1,:]\n",
    "        n_0 = _normalize(torch.cross(u_0, u_1), dim=-1)\n",
    "        b_1 = _normalize(u_0 - u_1, dim=-1)\n",
    "        \n",
    "        # select C3'\n",
    "        n_0 = n_0[:,4::6,:] \n",
    "        b_1 = b_1[:,4::6,:]\n",
    "        X = X[:,4::6,:]\n",
    "\n",
    "        Q = torch.stack((b_1, n_0, torch.cross(b_1, n_0)), 2)\n",
    "        Q = Q.view(list(Q.shape[:2]) + [9])\n",
    "        Q = F.pad(Q, (0,0,0,1), 'constant', 0) # [16, 464, 9]\n",
    "\n",
    "        Q_neighbors = gather_nodes(Q, E_idx) # [16, 464, 30, 9]\n",
    "        P_neighbors = gather_nodes(V[:,:,0,:], E_idx) # [16, 464, 30, 3]\n",
    "        O5_neighbors = gather_nodes(V[:,:,1,:], E_idx)\n",
    "        C5_neighbors = gather_nodes(V[:,:,2,:], E_idx)\n",
    "        C4_neighbors = gather_nodes(V[:,:,3,:], E_idx)\n",
    "        O3_neighbors = gather_nodes(V[:,:,5,:], E_idx)\n",
    "        \n",
    "        Q = Q.view(list(Q.shape[:2]) + [3,3]).unsqueeze(2) # [16, 464, 1, 3, 3]\n",
    "        Q_neighbors = Q_neighbors.view(list(Q_neighbors.shape[:3]) + [3,3]) # [16, 464, 30, 3, 3]\n",
    "\n",
    "        dX = torch.stack([P_neighbors,O5_neighbors,C5_neighbors,C4_neighbors,O3_neighbors], dim=3) - X[:,:,None,None,:] # [16, 464, 30, 3]\n",
    "        dU = torch.matmul(Q[:,:,:,None,:,:], dX[...,None]).squeeze(-1) # [16, 464, 30, 3] 邻居的相对坐标\n",
    "        B, N, K = dU.shape[:3]\n",
    "        E_direct = _normalize(dU, dim=-1)\n",
    "        E_direct = E_direct.reshape(B, N, K,-1)\n",
    "        R = torch.matmul(Q.transpose(-1,-2), Q_neighbors)\n",
    "        E_orient = self._quaternions(R)\n",
    "        \n",
    "        dX_inner = V[:,:,[0,2,3],:] - X.unsqueeze(-2)\n",
    "        dU_inner = torch.matmul(Q, dX_inner.unsqueeze(-1)).squeeze(-1)\n",
    "        dU_inner = _normalize(dU_inner, dim=-1)\n",
    "        V_direct = dU_inner.reshape(B,N,-1)\n",
    "        return V_direct, E_direct, E_orient\n",
    "\n",
    "\n",
    "    def _dihedrals(self, X, eps=1e-7):\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        X = X[:,:,:6,:].reshape(X.shape[0], 6*X.shape[1], 3)\n",
    "\n",
    "        # Shifted slices of unit vectors\n",
    "        # https://iupac.qmul.ac.uk/misc/pnuc2.html#220\n",
    "        # https://x3dna.org/highlights/torsion-angles-of-nucleic-acid-structures\n",
    "        # alpha:   O3'_{i-1} P_i O5'_i C5'_i\n",
    "        # beta:    P_i O5'_i C5'_i C4'_i\n",
    "        # gamma:   O5'_i C5'_i C4'_i C3'_i\n",
    "        # delta:   C5'_i C4'_i C3'_i O3'_i\n",
    "        # epsilon: C4'_i C3'_i O3'_i P_{i+1}\n",
    "        # zeta:    C3'_i O3'_i P_{i+1} O5'_{i+1} \n",
    "        # What's more:\n",
    "        #   chi: C1' - N9 \n",
    "        #   chi is different for (C, T, U) and (A, G) https://x3dna.org/highlights/the-chi-x-torsion-angle-characterizes-base-sugar-relative-orientation\n",
    "\n",
    "        dX = X[:, 5:, :] - X[:, :-5, :] # O3'-P, P-O5', O5'-C5', C5'-C4', ...\n",
    "        U = F.normalize(dX, dim=-1)\n",
    "        u_2 = U[:,:-2,:]  # O3'-P, P-O5', ...\n",
    "        u_1 = U[:,1:-1,:] # P-O5', O5'-C5', ...\n",
    "        u_0 = U[:,2:,:]   # O5'-C5', C5'-C4', ...\n",
    "        # Backbone normals\n",
    "        n_2 = F.normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)\n",
    "        n_1 = F.normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)\n",
    "\n",
    "        # Angle between normals\n",
    "        cosD = (n_2 * n_1).sum(-1)\n",
    "        cosD = torch.clamp(cosD, -1+eps, 1-eps)\n",
    "        D = torch.sign((u_2 * n_1).sum(-1)) * torch.acos(cosD)\n",
    "        \n",
    "        D = F.pad(D, (3,4), 'constant', 0)\n",
    "        D = D.view((D.size(0), D.size(1) //6, 6))\n",
    "        return torch.cat((torch.cos(D), torch.sin(D)), 2) # return D_features\n",
    "\n",
    "\n",
    "    def encode_node_features(self, X, mask_bool, E_idx):\n",
    "        # node features\n",
    "        h_V = []\n",
    "        node_mask_select = lambda x: torch.masked_select(x, mask_bool.unsqueeze(-1)).reshape(-1, x.shape[-1])\n",
    "        node_feat_types = self.node_feat_types\n",
    "        # angle\n",
    "        V_angle = node_mask_select(self._dihedrals(X))\n",
    "        # distance\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        atom_P = X[:, :, 0, :]\n",
    "        atom_O5_ = X[:, :, 1, :]\n",
    "        atom_C5_ = X[:, :, 2, :]\n",
    "        atom_C4_ = X[:, :, 3, :]\n",
    "        atom_C3_ = X[:, :, 4, :]\n",
    "        atom_O3_ = X[:, :, 5, :]\n",
    "        node_list = ['O5_-P', 'C5_-P', 'C4_-P', 'C3_-P', 'O3_-P']\n",
    "        V_dist = []\n",
    "        for pair in node_list:\n",
    "            atom1, atom2 = pair.split('-')\n",
    "            V_dist.append(node_mask_select(self._get_rbf(vars()['atom_' + atom1], vars()['atom_' + atom2], None, self.num_rbf).squeeze()))\n",
    "        V_dist = torch.cat(tuple(V_dist), dim=-1).squeeze()\n",
    "        # direction\n",
    "        V_direct, E_direct, E_orient = self._orientations_coarse(X, E_idx)\n",
    "        V_direct = node_mask_select(V_direct)\n",
    "        if 'angle' in node_feat_types:\n",
    "            h_V.append(V_angle)\n",
    "        if 'distance' in node_feat_types:\n",
    "            h_V.append(V_dist)\n",
    "        if 'direction' in node_feat_types:\n",
    "            h_V.append(V_direct)\n",
    "        \n",
    "        return self.node_embedding(torch.cat(h_V, dim=-1))\n",
    "\n",
    "    def encode_edge_features(self, X, mask_attend, E_idx):\n",
    "        # edge features\n",
    "        h_E = []\n",
    "        edge_mask_select = lambda x: torch.masked_select(x, mask_attend.unsqueeze(-1)).reshape(-1,x.shape[-1])\n",
    "        edge_feat_types = self.edge_feat_types\n",
    "        # direction\n",
    "        V_direct, E_direct, E_orient = self._orientations_coarse(X, E_idx)\n",
    "        E_direct, E_orient = list(map(lambda x: edge_mask_select(x), [E_direct, E_orient]))\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        atom_P = X[:, :, 0, :]\n",
    "        atom_O5_ = X[:, :, 1, :]\n",
    "        atom_C5_ = X[:, :, 2, :]\n",
    "        atom_C4_ = X[:, :, 3, :]\n",
    "        atom_C3_ = X[:, :, 4, :]\n",
    "        atom_O3_ = X[:, :, 5, :]\n",
    "        edge_list = ['P-P', 'O5_-P', 'C5_-P', 'C4_-P', 'C3_-P', 'O3_-P']\n",
    "        E_dist = [] \n",
    "        for pair in edge_list:\n",
    "            atom1, atom2 = pair.split('-')\n",
    "            E_dist.append(edge_mask_select(self._get_rbf(vars()['atom_' + atom1], vars()['atom_' + atom2], E_idx, self.num_rbf)))\n",
    "        E_dist = torch.cat(tuple(E_dist), dim=-1)\n",
    "        \n",
    "        if 'orientation' in edge_feat_types:\n",
    "            h_E.append(E_orient)\n",
    "        if 'distance' in edge_feat_types:\n",
    "            h_E.append(E_dist)\n",
    "        if 'direction' in edge_feat_types:\n",
    "            h_E.append(E_direct)\n",
    "        return self.edge_embedding(torch.cat(h_E, dim=-1))\n",
    "\n",
    "\n",
    "    def forward(self, X, mask):\n",
    "        \"\"\"\n",
    "        X: [B, N, 6, 3], batch,  N最大序列长度，6个原子位置，每个原子坐标\n",
    "        mask: [B, N]  # 标识每个样本序列的有效长度1有效，0无效\n",
    "        \"\"\"\n",
    "        if self.training and self.augment_eps > 0:\n",
    "            X = X + self.augment_eps * torch.randn_like(X)\n",
    "\n",
    "        # Build k-Nearest Neighbors graph\n",
    "        B, N, _,_ = X.shape\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        atom_P = X[:, :, 0, :]\n",
    "        atom_O5_ = X[:, :, 1, :]\n",
    "        atom_C5_ = X[:, :, 2, :]\n",
    "        atom_C4_ = X[:, :, 3, :]\n",
    "        atom_C3_ = X[:, :, 4, :]\n",
    "        atom_O3_ = X[:, :, 5, :]\n",
    "        # atom_N19_ = X[:, :, 6, :]\n",
    "\n",
    "        X_backbone = atom_P  # 以P基团为中心判断邻域\n",
    "        D_neighbors, E_idx = self._dist(X_backbone, mask, self.top_k) # 获取topk近邻  返回每个节点的邻居和邻居id\n",
    "\n",
    "        mask_bool = (mask==1)\n",
    "        mask_attend = gather_nodes(mask.unsqueeze(-1), E_idx).squeeze(-1)\n",
    "        mask_attend = (mask.unsqueeze(-1) * mask_attend) == 1\n",
    "        \n",
    "        h_V = self.encode_node_features(X, mask_bool, E_idx)\n",
    "        h_E = self.encode_edge_features(X, mask_attend, E_idx)\n",
    "        \n",
    "        # Embed the nodes\n",
    "        h_V = self.norm_nodes(h_V)\n",
    "        h_E = self.norm_edges(h_E)\n",
    "\n",
    "        # prepare the variables to return\n",
    "        shift = mask.sum(dim=1).cumsum(dim=0) - mask.sum(dim=1)  # cumsum累积求和\n",
    "        src = shift.view(B,1,1) + E_idx\n",
    "        src = torch.masked_select(src, mask_attend).view(1,-1)\n",
    "        dst = shift.view(B,1,1) + torch.arange(0, N, device=src.device).view(1,-1,1).expand_as(mask_attend)\n",
    "        dst = torch.masked_select(dst, mask_attend).view(1,-1)\n",
    "        E_idx = torch.cat((dst, src), dim=0).long()\n",
    "\n",
    "        sparse_idx = mask.nonzero()\n",
    "        X = X[sparse_idx[:,0], sparse_idx[:,1], :, :]\n",
    "        batch_id = sparse_idx[:,0]\n",
    "        return h_V, h_E, E_idx, batch_id\n",
    "    \n",
    "X = torch.randn(1, 128, 6, 3)\n",
    "mask = torch.ones(1, 128)\n",
    "rna_graph = RNAGraphBuilder(128, 128)\n",
    "rna_graph(X, mask)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "fddb2bad-8121-404e-bd34-5f1be813f0de",
   "metadata": {},
   "outputs": [],
   "source": [
    "class RNAFeatures(nn.Module):\n",
    "    # 边特征维度，结点特征维度，结点特征类型，边特征类型，RBF核数，K近邻数，数据增强，dropout\n",
    "    # 结点特征：['angle', 'distance', 'direction'], 边特征：['orientation', 'distance', 'direction']\n",
    "    def __init__(self, edge_features, node_features, node_feat_types=[], edge_feat_types=[], num_rbf=16, top_k=30, augment_eps=0., dropout=0.1, args=None):\n",
    "        super(RNAFeatures, self).__init__()\n",
    "        \"\"\"Extract RNA Features\"\"\"\n",
    "        self.edge_features = edge_features\n",
    "        self.node_features = node_features\n",
    "        self.top_k = top_k\n",
    "        self.augment_eps = augment_eps \n",
    "        self.num_rbf = num_rbf\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "        self.node_feat_types = node_feat_types\n",
    "        self.edge_feat_types = edge_feat_types\n",
    "\n",
    "        node_in = sum([feat_dims['node'][feat] for feat in node_feat_types])\n",
    "        edge_in = sum([feat_dims['edge'][feat] for feat in edge_feat_types])\n",
    "        self.node_embedding = nn.Linear(node_in,  node_features, bias=True)\n",
    "        self.edge_embedding = nn.Linear(edge_in, edge_features, bias=True)\n",
    "        self.norm_nodes = Normalize(node_features)\n",
    "        self.norm_edges = Normalize(edge_features)\n",
    "        \n",
    "    def _dist(self, X, mask, eps=1E-6):\n",
    "        mask_2D = torch.unsqueeze(mask,1) * torch.unsqueeze(mask,2)  # 两两之间求掩码 B, N -> B, N, N\n",
    "        dX = torch.unsqueeze(X, 1) - torch.unsqueeze(X, 2)  # 两两之间求距离 B, N, 3 -> B, N, N, 3\n",
    "        D = (1. - mask_2D)*10000 + mask_2D* torch.sqrt(torch.sum(dX**2, 3) + eps)  #  B, N, N 求欧式距离, 无效值距离设置10000的很大值\n",
    "\n",
    "        D_max, _ = torch.max(D, -1, keepdim=True)  # 获取每行的最大值\n",
    "        D_adjust = D + (1. - mask_2D) * (D_max+1)  # 无效值设置为最大值+1, 不会被选中\n",
    "        D_neighbors, E_idx = torch.topk(D_adjust, min(self.top_k, D_adjust.shape[-1]), dim=-1, largest=False) # 选择topk近邻\n",
    "        return D_neighbors, E_idx\n",
    "    \n",
    "    def _rbf(self, D):\n",
    "        D_min, D_max, D_count = 0., 20., self.num_rbf\n",
    "        D_mu = torch.linspace(D_min, D_max, D_count, device=D.device)\n",
    "        D_mu = D_mu.view([1,1,1,-1])\n",
    "        D_sigma = (D_max - D_min) / D_count\n",
    "        D_expand = torch.unsqueeze(D, -1)\n",
    "        return torch.exp(-((D_expand - D_mu) / D_sigma)**2)\n",
    "    \n",
    "    def _get_rbf(self, A, B, E_idx=None, num_rbf=16):\n",
    "        if E_idx is not None:\n",
    "            D_A_B = torch.sqrt(torch.sum((A[:,:,None,:] - B[:,None,:,:])**2,-1) + 1e-6)\n",
    "            D_A_B_neighbors = gather_edges(D_A_B[:,:,:,None], E_idx)[:,:,:,0]\n",
    "            RBF_A_B = self._rbf(D_A_B_neighbors)\n",
    "        else:\n",
    "            D_A_B = torch.sqrt(torch.sum((A[:,:,None,:] - B[:,:,None,:])**2,-1) + 1e-6)\n",
    "            RBF_A_B = self._rbf(D_A_B)\n",
    "        return RBF_A_B\n",
    "    \n",
    "    def _quaternions(self, R):\n",
    "        diag = torch.diagonal(R, dim1=-2, dim2=-1)\n",
    "        Rxx, Ryy, Rzz = diag.unbind(-1)\n",
    "        magnitudes = 0.5 * torch.sqrt(torch.abs(1 + torch.stack([\n",
    "              Rxx - Ryy - Rzz, \n",
    "            - Rxx + Ryy - Rzz, \n",
    "            - Rxx - Ryy + Rzz\n",
    "        ], -1)))\n",
    "        _R = lambda i,j: R[:,:,:,i,j]\n",
    "        signs = torch.sign(torch.stack([\n",
    "            _R(2,1) - _R(1,2),\n",
    "            _R(0,2) - _R(2,0),\n",
    "            _R(1,0) - _R(0,1)\n",
    "        ], -1))\n",
    "        xyz = signs * magnitudes\n",
    "        w = torch.sqrt(F.relu(1 + diag.sum(-1, keepdim=True))) / 2.\n",
    "        Q = torch.cat((xyz, w), -1)\n",
    "        Q = F.normalize(Q, dim=-1)\n",
    "        return Q\n",
    "    \n",
    "    def _orientations_coarse(self, X, E_idx, eps=1e-6):\n",
    "        V = X.clone()\n",
    "        X = X[:,:,:6,:].reshape(X.shape[0], 6*X.shape[1], 3) \n",
    "        dX = X[:,1:,:] - X[:,:-1,:]\n",
    "        U = _normalize(dX, dim=-1)\n",
    "        u_0, u_1 = U[:,:-2,:], U[:,1:-1,:]\n",
    "        n_0 = _normalize(torch.cross(u_0, u_1), dim=-1)\n",
    "        b_1 = _normalize(u_0 - u_1, dim=-1)\n",
    "        \n",
    "        # select C3'\n",
    "        n_0 = n_0[:,4::6,:] \n",
    "        b_1 = b_1[:,4::6,:]\n",
    "        X = X[:,4::6,:]\n",
    "\n",
    "        Q = torch.stack((b_1, n_0, torch.cross(b_1, n_0)), 2)\n",
    "        Q = Q.view(list(Q.shape[:2]) + [9])\n",
    "        Q = F.pad(Q, (0,0,0,1), 'constant', 0) # [16, 464, 9]\n",
    "\n",
    "        Q_neighbors = gather_nodes(Q, E_idx) # [16, 464, 30, 9]\n",
    "        P_neighbors = gather_nodes(V[:,:,0,:], E_idx) # [16, 464, 30, 3]\n",
    "        O5_neighbors = gather_nodes(V[:,:,1,:], E_idx)\n",
    "        C5_neighbors = gather_nodes(V[:,:,2,:], E_idx)\n",
    "        C4_neighbors = gather_nodes(V[:,:,3,:], E_idx)\n",
    "        O3_neighbors = gather_nodes(V[:,:,5,:], E_idx)\n",
    "        \n",
    "        Q = Q.view(list(Q.shape[:2]) + [3,3]).unsqueeze(2) # [16, 464, 1, 3, 3]\n",
    "        Q_neighbors = Q_neighbors.view(list(Q_neighbors.shape[:3]) + [3,3]) # [16, 464, 30, 3, 3]\n",
    "\n",
    "        dX = torch.stack([P_neighbors,O5_neighbors,C5_neighbors,C4_neighbors,O3_neighbors], dim=3) - X[:,:,None,None,:] # [16, 464, 30, 3]\n",
    "        dU = torch.matmul(Q[:,:,:,None,:,:], dX[...,None]).squeeze(-1) # [16, 464, 30, 3] 邻居的相对坐标\n",
    "        B, N, K = dU.shape[:3]\n",
    "        E_direct = _normalize(dU, dim=-1)\n",
    "        E_direct = E_direct.reshape(B, N, K,-1)\n",
    "        R = torch.matmul(Q.transpose(-1,-2), Q_neighbors)\n",
    "        E_orient = self._quaternions(R)\n",
    "        \n",
    "        dX_inner = V[:,:,[0,2,3],:] - X.unsqueeze(-2)\n",
    "        dU_inner = torch.matmul(Q, dX_inner.unsqueeze(-1)).squeeze(-1)\n",
    "        dU_inner = _normalize(dU_inner, dim=-1)\n",
    "        V_direct = dU_inner.reshape(B,N,-1)\n",
    "        return V_direct, E_direct, E_orient\n",
    "    \n",
    "    def _dihedrals(self, X, eps=1e-7):\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        X = X[:,:,:6,:].reshape(X.shape[0], 6*X.shape[1], 3)\n",
    "\n",
    "        # Shifted slices of unit vectors\n",
    "        # https://iupac.qmul.ac.uk/misc/pnuc2.html#220\n",
    "        # https://x3dna.org/highlights/torsion-angles-of-nucleic-acid-structures\n",
    "        # alpha:   O3'_{i-1} P_i O5'_i C5'_i\n",
    "        # beta:    P_i O5'_i C5'_i C4'_i\n",
    "        # gamma:   O5'_i C5'_i C4'_i C3'_i\n",
    "        # delta:   C5'_i C4'_i C3'_i O3'_i\n",
    "        # epsilon: C4'_i C3'_i O3'_i P_{i+1}\n",
    "        # zeta:    C3'_i O3'_i P_{i+1} O5'_{i+1} \n",
    "        # What's more:\n",
    "        #   chi: C1' - N9 \n",
    "        #   chi is different for (C, T, U) and (A, G) https://x3dna.org/highlights/the-chi-x-torsion-angle-characterizes-base-sugar-relative-orientation\n",
    "\n",
    "        dX = X[:, 5:, :] - X[:, :-5, :] # O3'-P, P-O5', O5'-C5', C5'-C4', ...\n",
    "        U = F.normalize(dX, dim=-1)\n",
    "        u_2 = U[:,:-2,:]  # O3'-P, P-O5', ...\n",
    "        u_1 = U[:,1:-1,:] # P-O5', O5'-C5', ...\n",
    "        u_0 = U[:,2:,:]   # O5'-C5', C5'-C4', ...\n",
    "        # Backbone normals\n",
    "        n_2 = F.normalize(torch.cross(u_2, u_1), dim=-1)\n",
    "        n_1 = F.normalize(torch.cross(u_1, u_0), dim=-1)\n",
    "\n",
    "        # Angle between normals\n",
    "        cosD = (n_2 * n_1).sum(-1)\n",
    "        cosD = torch.clamp(cosD, -1+eps, 1-eps)\n",
    "        D = torch.sign((u_2 * n_1).sum(-1)) * torch.acos(cosD)\n",
    "        \n",
    "        D = F.pad(D, (3,4), 'constant', 0)\n",
    "        D = D.view((D.size(0), D.size(1) //6, 6))\n",
    "        return torch.cat((torch.cos(D), torch.sin(D)), 2) # return D_features\n",
    "\n",
    "    def forward(self, X, mask):\n",
    "        \"\"\"\n",
    "        X: [B, N, 6, 3], batch,  N最大序列长度，6个原子位置，每个原子坐标\n",
    "        mask: [B, N]  # 标识每个样本序列的有效长度1有效，0无效\n",
    "        \"\"\"\n",
    "        if self.training and self.augment_eps > 0:\n",
    "            X = X + self.augment_eps * torch.randn_like(X)\n",
    "\n",
    "        # Build k-Nearest Neighbors graph\n",
    "        B, N, _,_ = X.shape\n",
    "        # P, O5', C5', C4', C3', O3'\n",
    "        atom_P = X[:, :, 0, :]\n",
    "        atom_O5_ = X[:, :, 1, :]\n",
    "        atom_C5_ = X[:, :, 2, :]\n",
    "        atom_C4_ = X[:, :, 3, :]\n",
    "        atom_C3_ = X[:, :, 4, :] \n",
    "        atom_O3_ = X[:, :, 5, :]\n",
    "        # atom_N19_ = X[:, :, 6, :]\n",
    "\n",
    "        X_backbone = atom_P  # 以P基团为中心判断邻域\n",
    "        D_neighbors, E_idx = self._dist(X_backbone, mask) # 获取topk近邻  返回每个节点的邻居和邻居id\n",
    "\n",
    "        mask_bool = (mask==1)\n",
    "        mask_attend = gather_nodes(mask.unsqueeze(-1), E_idx).squeeze(-1)\n",
    "        mask_attend = (mask.unsqueeze(-1) * mask_attend) == 1\n",
    "        edge_mask_select = lambda x: torch.masked_select(x, mask_attend.unsqueeze(-1)).reshape(-1,x.shape[-1])\n",
    "        node_mask_select = lambda x: torch.masked_select(x, mask_bool.unsqueeze(-1)).reshape(-1, x.shape[-1])\n",
    "\n",
    "        # node features\n",
    "        h_V = []\n",
    "        # angle\n",
    "        V_angle = node_mask_select(self._dihedrals(X))\n",
    "        # distance\n",
    "        node_list = ['O5_-P', 'C5_-P', 'C4_-P', 'C3_-P', 'O3_-P']\n",
    "        V_dist = []\n",
    "        \n",
    "        for pair in node_list:\n",
    "            atom1, atom2 = pair.split('-')\n",
    "            V_dist.append(node_mask_select(self._get_rbf(vars()['atom_' + atom1], vars()['atom_' + atom2], None, self.num_rbf).squeeze()))\n",
    "        V_dist = torch.cat(tuple(V_dist), dim=-1).squeeze()\n",
    "        # direction\n",
    "        V_direct, E_direct, E_orient = self._orientations_coarse(X, E_idx)\n",
    "        V_direct = node_mask_select(V_direct)\n",
    "\n",
    "\n",
    "        # edge features\n",
    "        h_E = []\n",
    "        E_direct, E_orient = list(map(lambda x: edge_mask_select(x), [E_direct, E_orient]))\n",
    "        # dist\n",
    "        edge_list = ['P-P', 'O5_-P', 'C5_-P', 'C4_-P', 'C3_-P', 'O3_-P']\n",
    "        E_dist = [] \n",
    "        for pair in edge_list:\n",
    "            atom1, atom2 = pair.split('-')\n",
    "            E_dist.append(edge_mask_select(self._get_rbf(vars()['atom_' + atom1], vars()['atom_' + atom2], E_idx, self.num_rbf)))\n",
    "        E_dist = torch.cat(tuple(E_dist), dim=-1)\n",
    "\n",
    "        if 'angle' in self.node_feat_types:\n",
    "            h_V.append(V_angle)\n",
    "        if 'distance' in self.node_feat_types:\n",
    "            h_V.append(V_dist)\n",
    "        if 'direction' in self.node_feat_types:\n",
    "            h_V.append(V_direct)\n",
    "\n",
    "        if 'orientation' in self.edge_feat_types:\n",
    "            h_E.append(E_orient)\n",
    "        if 'distance' in self.edge_feat_types:\n",
    "            h_E.append(E_dist)\n",
    "        if 'direction' in self.edge_feat_types:\n",
    "            h_E.append(E_direct)\n",
    "            \n",
    "        # Embed the nodes\n",
    "        h_V = self.norm_nodes(self.node_embedding(torch.cat(h_V, dim=-1)))\n",
    "        h_E = self.norm_edges(self.edge_embedding(torch.cat(h_E, dim=-1)))\n",
    "\n",
    "        # prepare the variables to return\n",
    "        # S = torch.masked_select(S, (mask==1))\n",
    "        shift = mask.sum(dim=1).cumsum(dim=0) - mask.sum(dim=1)  # cumsum累积求和\n",
    "        src = shift.view(B,1,1) + E_idx\n",
    "        src = torch.masked_select(src, mask_attend).view(1,-1)\n",
    "        dst = shift.view(B,1,1) + torch.arange(0, N, device=src.device).view(1,-1,1).expand_as(mask_attend)\n",
    "        dst = torch.masked_select(dst, mask_attend).view(1,-1)\n",
    "        E_idx = torch.cat((dst, src), dim=0).long()\n",
    "\n",
    "        sparse_idx = mask.nonzero()\n",
    "        X = X[sparse_idx[:,0], sparse_idx[:,1], :, :]\n",
    "        batch_id = sparse_idx[:,0]\n",
    "        return h_V, h_E, E_idx, batch_id"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "81d99837",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([1, 1])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = torch.tensor([[1,2],[1,4]])\n",
    "mask_bool = a == 1\n",
    "mask_bool\n",
    "S = torch.masked_select(a, mask_bool)\n",
    "S"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "e12b215f-66ff-46cb-8645-733655cbf66f",
   "metadata": {},
   "outputs": [],
   "source": [
    "class RNAModel(nn.Module):\n",
    "    def __init__(self, model_config):\n",
    "        super(RNAModel, self).__init__()\n",
    "\n",
    "        self.smoothing = model_config.smoothing\n",
    "        self.node_features = self.edge_features = model_config.hidden\n",
    "        self.hidden_dim = model_config.hidden\n",
    "        self.vocab = model_config.vocab_size\n",
    "\n",
    "        # self.features = RNAFeatures(\n",
    "        #     model_config.hidden, model_config.hidden, \n",
    "        #     top_k=model_config.k_neighbors, \n",
    "        #     dropout=model_config.dropout,\n",
    "        #     node_feat_types=model_config.node_feat_types, \n",
    "        #     edge_feat_types=model_config.edge_feat_types,\n",
    "        #     args=model_config\n",
    "        # )\n",
    "        \n",
    "        self.features = RNAGraphBuilder(model_config.hidden, model_config.hidden,\n",
    "                                        top_k=model_config.k_neighbors)\n",
    "\n",
    "        layer = MPNNLayer\n",
    "        self.W_s = nn.Embedding(model_config.vocab_size, self.hidden_dim)\n",
    "        self.encoder_layers = nn.ModuleList([\n",
    "            layer(self.hidden_dim, self.hidden_dim*2, dropout=model_config.dropout)\n",
    "            for _ in range(model_config.num_encoder_layers)])\n",
    "        self.decoder_layers = nn.ModuleList([\n",
    "            layer(self.hidden_dim, self.hidden_dim*2, dropout=model_config.dropout)\n",
    "            for _ in range(model_config.num_decoder_layers)])\n",
    "\n",
    "        self.projection_head = nn.Sequential(\n",
    "            nn.Linear(self.hidden_dim, self.hidden_dim, bias=False), \n",
    "            nn.ReLU(inplace=True), \n",
    "            nn.Linear(self.hidden_dim, self.hidden_dim, bias=True)\n",
    "        )\n",
    "        # 结点四分类\n",
    "        self.readout = nn.Linear(self.hidden_dim, model_config.vocab_size, bias=True)\n",
    "\n",
    "        for p in self.parameters():\n",
    "            if p.dim() > 1:\n",
    "                nn.init.xavier_uniform_(p)\n",
    "\n",
    "\n",
    "    def forward(self, X, mask):\n",
    "        # 抽取结点特征，边特征， 边索引，批次索引\n",
    "        h_V, h_E, E_idx, batch_id = self.features(X, mask)\n",
    "        \n",
    "        # 边特征保持不变，聚合边特征到结点\n",
    "        for enc_layer in self.encoder_layers:\n",
    "            h_EV = torch.cat([h_E, h_V[E_idx[0]], h_V[E_idx[1]]], dim=-1)\n",
    "            h_V = enc_layer(h_V, h_EV, E_idx, batch_id)\n",
    "        # 边特征保持不变，再次聚合边特征到结点\n",
    "        for dec_layer in self.decoder_layers:\n",
    "            h_EV = torch.cat([h_E, h_V[E_idx[0]], h_V[E_idx[1]]], dim=-1)\n",
    "            h_V = dec_layer(h_V, h_EV, E_idx, batch_id)\n",
    "\n",
    "        graph_embs = []\n",
    "        # 遍历每个样本\n",
    "        for b_id in range(batch_id[-1].item()+1):\n",
    "            # 求均值\n",
    "            b_data = h_V[batch_id == b_id].mean(0)\n",
    "            graph_embs.append(b_data)\n",
    "        graph_embs = torch.stack(graph_embs, dim=0)\n",
    "        # 全连接层\n",
    "        graph_prjs = self.projection_head(graph_embs)\n",
    "        # 碱基四分类器\n",
    "        logits = self.readout(h_V)\n",
    "        return logits, graph_prjs\n",
    "\n",
    "\n",
    "    # 废弃\n",
    "    def sample(self, X, S, mask=None):\n",
    "        X, gt_S, h_V, h_E, E_idx, batch_id = self.features(X, S, mask) \n",
    "\n",
    "        for enc_layer in self.encoder_layers:\n",
    "            h_EV = torch.cat([h_E, h_V[E_idx[0]], h_V[E_idx[1]]], dim=-1)\n",
    "            h_V = enc_layer(h_V, h_EV, E_idx, batch_id)\n",
    "\n",
    "        for dec_layer in self.decoder_layers:\n",
    "            h_EV = torch.cat([h_E, h_V[E_idx[0]], h_V[E_idx[1]]], dim=-1)\n",
    "            h_V = dec_layer(h_V, h_EV, E_idx, batch_id)\n",
    "\n",
    "        logits = self.readout(h_V)\n",
    "        return logits, gt_S"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6fce9f8d-d53a-48a1-a082-1047dca20c5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "RNAModel(\n",
      "  (features): RNAGraphBuilder(\n",
      "    (node_embedding): Linear(in_features=101, out_features=128, bias=True)\n",
      "    (edge_embedding): Linear(in_features=115, out_features=128, bias=True)\n",
      "    (norm_nodes): Normalize()\n",
      "    (norm_edges): Normalize()\n",
      "  )\n",
      "  (W_s): Embedding(4, 128)\n",
      "  (encoder_layers): ModuleList(\n",
      "    (0): MPNNLayer(\n",
      "      (dropout): Dropout(p=0.1, inplace=False)\n",
      "      (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (W1): Linear(in_features=384, out_features=128, bias=True)\n",
      "      (W2): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (W3): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (act): ReLU()\n",
      "      (dense): Sequential(\n",
      "        (0): Linear(in_features=128, out_features=512, bias=True)\n",
      "        (1): ReLU()\n",
      "        (2): Linear(in_features=512, out_features=128, bias=True)\n",
      "      )\n",
      "    )\n",
      "    (1): MPNNLayer(\n",
      "      (dropout): Dropout(p=0.1, inplace=False)\n",
      "      (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (W1): Linear(in_features=384, out_features=128, bias=True)\n",
      "      (W2): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (W3): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (act): ReLU()\n",
      "      (dense): Sequential(\n",
      "        (0): Linear(in_features=128, out_features=512, bias=True)\n",
      "        (1): ReLU()\n",
      "        (2): Linear(in_features=512, out_features=128, bias=True)\n",
      "      )\n",
      "    )\n",
      "    (2): MPNNLayer(\n",
      "      (dropout): Dropout(p=0.1, inplace=False)\n",
      "      (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (W1): Linear(in_features=384, out_features=128, bias=True)\n",
      "      (W2): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (W3): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (act): ReLU()\n",
      "      (dense): Sequential(\n",
      "        (0): Linear(in_features=128, out_features=512, bias=True)\n",
      "        (1): ReLU()\n",
      "        (2): Linear(in_features=512, out_features=128, bias=True)\n",
      "      )\n",
      "    )\n",
      "  )\n",
      "  (decoder_layers): ModuleList(\n",
      "    (0): MPNNLayer(\n",
      "      (dropout): Dropout(p=0.1, inplace=False)\n",
      "      (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (W1): Linear(in_features=384, out_features=128, bias=True)\n",
      "      (W2): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (W3): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (act): ReLU()\n",
      "      (dense): Sequential(\n",
      "        (0): Linear(in_features=128, out_features=512, bias=True)\n",
      "        (1): ReLU()\n",
      "        (2): Linear(in_features=512, out_features=128, bias=True)\n",
      "      )\n",
      "    )\n",
      "    (1): MPNNLayer(\n",
      "      (dropout): Dropout(p=0.1, inplace=False)\n",
      "      (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (W1): Linear(in_features=384, out_features=128, bias=True)\n",
      "      (W2): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (W3): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (act): ReLU()\n",
      "      (dense): Sequential(\n",
      "        (0): Linear(in_features=128, out_features=512, bias=True)\n",
      "        (1): ReLU()\n",
      "        (2): Linear(in_features=512, out_features=128, bias=True)\n",
      "      )\n",
      "    )\n",
      "    (2): MPNNLayer(\n",
      "      (dropout): Dropout(p=0.1, inplace=False)\n",
      "      (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)\n",
      "      (W1): Linear(in_features=384, out_features=128, bias=True)\n",
      "      (W2): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (W3): Linear(in_features=128, out_features=128, bias=True)\n",
      "      (act): ReLU()\n",
      "      (dense): Sequential(\n",
      "        (0): Linear(in_features=128, out_features=512, bias=True)\n",
      "        (1): ReLU()\n",
      "        (2): Linear(in_features=512, out_features=128, bias=True)\n",
      "      )\n",
      "    )\n",
      "  )\n",
      "  (projection_head): Sequential(\n",
      "    (0): Linear(in_features=128, out_features=128, bias=False)\n",
      "    (1): ReLU(inplace=True)\n",
      "    (2): Linear(in_features=128, out_features=128, bias=True)\n",
      "  )\n",
      "  (readout): Linear(in_features=128, out_features=4, bias=True)\n",
      ")\n"
     ]
    }
   ],
   "source": [
    "model = RNAModel(config.model_config).to(config.device)\n",
    "print(model)\n",
    "print(model.training)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "528c5443",
   "metadata": {},
   "source": [
    "### training"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa10ad13-dc08-4515-b2e0-3fe96bee7d0d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from torch.optim.lr_scheduler import LambdaLR\n",
    "\n",
    "optimizer = Adam(model.parameters(), train_config.lr, weight_decay=1e-4)\n",
    "criterion = nn.CrossEntropyLoss()\n",
    "    \n",
    "# Warmup学习率调度器\n",
    "def get_warmup_scheduler(optimizer, total_steps, warmup_steps=100, gamma=0.3, step_rate=0.3,  min_times=1e-3):\n",
    "    # 生成一个乘数，用于乘初始学习率\n",
    "    def lr_lambda(current_step):\n",
    "        # 先线性增加\n",
    "        if current_step < warmup_steps:\n",
    "            lr_decay = float(current_step) / float(max(1, warmup_steps))\n",
    "        elif current_step < total_steps:\n",
    "            step_size = max(1, (total_steps - warmup_steps) * step_rate)\n",
    "            lr_decay = gamma ** ((current_step - warmup_steps) // step_size)\n",
    "        else:\n",
    "            # 最后的min_times步学习率不变\n",
    "            lr_decay = min_times\n",
    "        return lr_decay\n",
    "    \n",
    "    return LambdaLR(optimizer, lr_lambda)\n",
    "\n",
    "# 假设总共有10000个steps，其中前1000个steps用于warmup\n",
    "num_warmup_steps = 100  # 100可以迅速第一个epoch就学习\n",
    "total_steps = train_config.epoch * len(train_loader)\n",
    "scheduler = get_warmup_scheduler(optimizer, total_steps, num_warmup_steps)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "dac46261",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20400"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_config.epoch * len(train_loader)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e18a8175-3562-4f27-a273-1b7725959ae4",
   "metadata": {},
   "outputs": [],
   "source": [
    "if not os.path.exists(train_config.output_dir):\n",
    "    os.makedirs(train_config.output_dir)\n",
    "\n",
    "best_valid_recovery = 0\n",
    "\n",
    "accumulation_steps = 1\n",
    "for epoch in range(train_config.epoch):\n",
    "    # 开启训练模式\n",
    "    model.train()\n",
    "    epoch_loss = 0\n",
    "    train_pbar = tqdm(train_loader)\n",
    "    \n",
    "    # 梯度初始化\n",
    "    optimizer.zero_grad()\n",
    "    for i, batch in enumerate(train_pbar):\n",
    "        X, S, mask, lengths, names = batch\n",
    "        X = X.to(config.device)\n",
    "        S = S.to(config.device)\n",
    "        mask = mask.to(config.device)\n",
    "        \n",
    "        logits, _ = model(X, mask)\n",
    "        S_masked = torch.masked_select(S, (mask == 1))\n",
    "        loss = criterion(logits, S_masked)\n",
    "        \n",
    "        # 梯度归一化（可选）\n",
    "        loss = loss / accumulation_steps  # 损失归一化，因为要进行梯度累加，所有每一步的梯度除累加步数\n",
    "        loss.backward()   # 梯度累积，反向传播计算梯度，多次调用，梯度会累加\n",
    "\n",
    "        # 每 accumulation_steps 步更新一次参数\n",
    "        if (i + 1) % accumulation_steps == 0:\n",
    "            optimizer.step()              # 参数更新，根据梯度更新参数\n",
    "            optimizer.zero_grad()         # 清空梯度缓存\n",
    "            scheduler.step()              # 更新学习率（batch级别）\n",
    "\n",
    "        epoch_loss += loss.item() * accumulation_steps  # 还原真实 loss 值，前面除了累加步数，这里再乘回来\n",
    "        train_pbar.set_description('train loss: {:.4f}'.format(loss.item() * accumulation_steps))\n",
    "\n",
    "    # 打印平均 loss\n",
    "    epoch_loss /= len(train_loader)\n",
    "    print('Epoch {}/{}, Train Loss: {:.4f}, lr: {:.4f}'.format(epoch + 1, train_config.epoch, epoch_loss, scheduler.get_last_lr()[0]))\n",
    "    torch.save(model.state_dict(), os.path.join(train_config.output_dir, 'last.pt'))\n",
    "    # 开启评估模式\n",
    "    model.eval()\n",
    "    epoch_loss = 0\n",
    "    with torch.no_grad():\n",
    "        recovery_list = []\n",
    "        for batch in tqdm(valid_loader):\n",
    "            X, S, mask, lengths, names = batch\n",
    "            X = X.to(config.device)\n",
    "            S = S.to(config.device)\n",
    "            mask = mask.to(config.device)\n",
    "            logits, _ = model(X, mask)\n",
    "            S = torch.masked_select(S, (mask==1))  # 选择有效的标签\n",
    "            loss = criterion(logits, S)\n",
    "            probs = F.softmax(logits, dim=-1)\n",
    "            samples = probs.argmax(dim=-1)\n",
    "            start_idx = 0\n",
    "            # 同一个batch每个样本的序列长度列表\n",
    "            for length in lengths:\n",
    "                end_idx = start_idx + length.item()\n",
    "                sample = samples[start_idx: end_idx]\n",
    "                gt_S = S[start_idx: end_idx]\n",
    "                arr = sample==gt_S\n",
    "                recovery = (sample==gt_S).sum() / len(sample)\n",
    "                recovery_list.append(recovery.cpu().numpy())\n",
    "                start_idx = end_idx\n",
    "            epoch_loss += loss.item()\n",
    "        # 打印平均 loss\n",
    "        epoch_loss /= len(valid_loader)\n",
    "        valid_recovery = np.mean(recovery_list)\n",
    "        print('Epoch {}/{}, Val Loss: {:.4f}, recovery: {:.4f}'.format(epoch + 1, train_config.epoch, epoch_loss, valid_recovery))\n",
    "        if valid_recovery > best_valid_recovery:\n",
    "            best_valid_recovery = valid_recovery\n",
    "            torch.save(model.state_dict(), os.path.join(train_config.output_dir, 'best.pt'))\n",
    "    torch.cuda.empty_cache()  # 释放缓存，使用频率不能太高，该方法本身比较耗时\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "9af13790",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.0007996059113300492]"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "scheduler.get_last_lr()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2122bf1d",
   "metadata": {},
   "source": [
    "### 显存不足报错\n",
    "\n",
    "RuntimeError: CUDA error: an illegal memory access was encountered\n",
    "CUDA kernel errors might be asynchronously reported at some other API call,so the stacktrace below might be incorrect.\n",
    "For debugging consider passing CUDA_LAUNCH_BLOCKING=1.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0f86d866-5712-4987-98a7-64606adb72f8",
   "metadata": {},
   "outputs": [],
   "source": [
    "eval_model = RNAModel(config.model_config).to(config.device)\n",
    "checkpoint_path = train_config.ckpt_path\n",
    "print(\"loading checkpoint from path:\", checkpoint_path)\n",
    "eval_model.load_state_dict(torch.load(checkpoint_path, map_location='cpu'), strict=True)\n",
    "eval_model.to(config.device)\n",
    "eval_model.eval()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "beac3fe1",
   "metadata": {},
   "source": [
    "### test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "10158a05-4192-4f93-b173-a7ba4dc25a96",
   "metadata": {},
   "outputs": [],
   "source": [
    "with torch.no_grad():\n",
    "    result_list = []\n",
    "    for batch in tqdm(test_loader):\n",
    "        X, S, mask, lengths, names = batch\n",
    "        X = X.to(config.device)\n",
    "        S = S.to(config.device)\n",
    "        mask = mask.to(config.device)\n",
    "        logits, _ = eval_model(X, mask)\n",
    "        S = torch.masked_select(S, (mask==1))  # 选择有效的标签\n",
    "        probs = F.softmax(logits, dim=-1)\n",
    "        samples = probs.argmax(dim=-1)\n",
    "        start_idx = 0\n",
    "        for length in lengths:\n",
    "            end_idx = start_idx + length.item()\n",
    "            sample = samples[start_idx: end_idx]\n",
    "            # print()\n",
    "            gt_S = S[start_idx: end_idx]\n",
    "            recovery = (sample==gt_S).sum() / len(sample)\n",
    "            recovery_list.append(recovery.cpu().numpy())\n",
    "            start_idx = end_idx\n",
    "    test_recovery = np.mean(recovery_list)\n",
    "    print('test recovery: {:.4f}'.format(test_recovery))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b00ce785",
   "metadata": {},
   "source": [
    "### Predict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bfb6d926",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'RNAModel' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "Cell \u001b[1;32mIn[1], line 1\u001b[0m\n\u001b[1;32m----> 1\u001b[0m model \u001b[38;5;241m=\u001b[39m \u001b[43mRNAModel\u001b[49m(config\u001b[38;5;241m.\u001b[39mmodel_config)\u001b[38;5;241m.\u001b[39mto(Config\u001b[38;5;241m.\u001b[39mdevice)\n\u001b[0;32m      2\u001b[0m \u001b[38;5;66;03m# print(model)\u001b[39;00m\n\u001b[0;32m      3\u001b[0m \u001b[38;5;66;03m# 加载模型权重\u001b[39;00m\n\u001b[0;32m      4\u001b[0m state_dict \u001b[38;5;241m=\u001b[39m torch\u001b[38;5;241m.\u001b[39mload(TrainConfig\u001b[38;5;241m.\u001b[39mckpt_path, map_location\u001b[38;5;241m=\u001b[39mConfig\u001b[38;5;241m.\u001b[39mdevice)\n",
      "\u001b[1;31mNameError\u001b[0m: name 'RNAModel' is not defined"
     ]
    }
   ],
   "source": [
    "model = RNAModel(config.model_config).to(Config.device)\n",
    "# print(model)\n",
    "# 加载模型权重\n",
    "state_dict = torch.load(TrainConfig.ckpt_path, map_location=Config.device)\n",
    "model.load_state_dict(state_dict)\n",
    "model.eval()\n",
    "\n",
    "recovery_list = []\n",
    "with torch.no_grad():\n",
    "    result_list = []\n",
    "    for batch in tqdm(test_loader):\n",
    "        X, S, mask, lengths, names = batch\n",
    "        X = X.to(config.device)\n",
    "        S = S.to(config.device)\n",
    "        mask = mask.to(config.device)\n",
    "        S = torch.masked_select(S, (mask==1))  # 选择有效的标签\n",
    "        logits, _ = model(X, mask)\n",
    "        probs = F.softmax(logits, dim=-1)\n",
    "        samples = probs.argmax(dim=-1)\n",
    "        start_idx = 0\n",
    "        for length in lengths:\n",
    "            end_idx = start_idx + length.item()\n",
    "            sample = samples[start_idx: end_idx]\n",
    "            # print()\n",
    "            \n",
    "            gt_S = S[start_idx: end_idx]\n",
    "            recovery = (sample==gt_S).sum() / len(sample)\n",
    "            recovery_list.append(recovery.cpu().numpy())\n",
    "            start_idx = end_idx\n",
    "    test_recovery = np.mean(recovery_list)\n",
    "    print('test recovery: {:.4f}'.format(test_recovery))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "test",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
